├── 130.txt ├── 65.txt ├── Backup.cpp ├── Check.cpp ├── Constants.h ├── DOC ├── paths.jpg └── successprob.jpg ├── GPU ├── GPUCompute.h ├── GPUEngine.cu ├── GPUEngine.h ├── GPUGenerate.cpp └── GPUMath.h ├── HashTable.cpp ├── HashTable.h ├── Kangaroo.cpp ├── Kangaroo.h ├── LICENSE ├── Makefile ├── Merge.cpp ├── Network.cpp ├── PartMerge.cpp ├── README.md ├── SECPK1 ├── Int.cpp ├── Int.h ├── IntGroup.cpp ├── IntGroup.h ├── IntMod.cpp ├── Point.cpp ├── Point.h ├── Random.cpp ├── Random.h ├── SECP256K1.cpp └── SECP256k1.h ├── Thread.cpp ├── Timer.cpp ├── Timer.h ├── VC_CUDA10 ├── Kangaroo.sln ├── Kangaroo.vcxproj └── Kangaroo.vcxproj.filters ├── VC_CUDA102 ├── Kangaroo.sln ├── Kangaroo.vcxproj └── Kangaroo.vcxproj.filters ├── VC_CUDA118 ├── Kangaroo.sln ├── Kangaroo.vcxproj └── Kangaroo.vcxproj.filters ├── VC_CUDA8 ├── Kangaroo.sln ├── Kangaroo.vcxproj └── Kangaroo.vcxproj.filters ├── WindowsErrors.h ├── detect_cuda.sh ├── deviceQuery ├── Makefile ├── NsightEclipse.xml ├── deviceQuery ├── deviceQuery.cpp ├── inc │ ├── helper_cuda.h │ └── helper_string.h └── readme.txt ├── main.cpp └── puzzle32.txt /130.txt: -------------------------------------------------------------------------------- 1 | 200000000000000000000000000000000 2 | 3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 3 | 03633CBE3EC02B9401C5EFFA144C5B4D22F87940259634858FC7E59B1C09937852 -------------------------------------------------------------------------------- /65.txt: -------------------------------------------------------------------------------- 1 | 10000000000000000 2 | 1ffffffffffffffff 3 | 0230210c23b1a047bc9bdbb13448e67deddc108946de6de639bcc75d47c0216b1b -------------------------------------------------------------------------------- /Check.cpp: -------------------------------------------------------------------------------- 1 | #include "Kangaroo.h" 2 | #include 3 | #include "SECPK1/IntGroup.h" 4 | #include "Timer.h" 5 | #include 6 | #define _USE_MATH_DEFINES 7 | #include 8 | #include 9 | #ifndef WIN64 10 | #include 11 | #define _strdup strdup 12 | #endif 13 | 14 | using namespace std; 15 | 16 | uint32_t Kangaroo::CheckHash(uint32_t h,uint32_t nbItem,HashTable* hT,FILE* f) { 17 | 18 | bool ok=true; 19 | vector dists; 20 | vector types; 21 | Point Z; 22 | Z.Clear(); 23 | uint32_t nbWrong = 0; 24 | ENTRY *items = NULL; 25 | ENTRY* e; 26 | 27 | if( hT ) { 28 | 29 | for(uint32_t i = 0; i < nbItem; i++) { 30 | e = hT->E[h].items[i]; 31 | Int dist; 32 | uint32_t kType = e->kType; 33 | HashTable::CalcDist(&(e->d),&dist); 34 | dists.push_back(dist); 35 | types.push_back(kType); 36 | } 37 | 38 | } else { 39 | 40 | items = (ENTRY*)malloc(nbItem * sizeof(ENTRY)); 41 | 42 | for(uint32_t i = 0; i < nbItem; i++) { 43 | ::fread(items+i,32,1,f); 44 | e = items + i; 45 | Int dist; 46 | uint32_t kType = e->kType; 47 | HashTable::CalcDist(&(e->d),&dist); 48 | dists.push_back(dist); 49 | types.push_back(kType); 50 | } 51 | 52 | } 53 | 54 | vector P = secp->ComputePublicKeys(dists); 55 | vector Sp; 56 | 57 | for(uint32_t i = 0; i < nbItem; i++) { 58 | 59 | if(types[i] == TAME) { 60 | Sp.push_back(Z); 61 | } else { 62 | Sp.push_back(keyToSearch); 63 | } 64 | 65 | } 66 | 67 | vector S = secp->AddDirect(Sp,P); 68 | 69 | for(uint32_t i = 0; i < nbItem; i++) { 70 | 71 | if(hT) e = hT->E[h].items[i]; 72 | else e = items + i; 73 | 74 | ok = (S[i].x.bits64[0] == e->x.i64[0]) && (S[i].x.bits64[1] == e->x.i64[1]) && (S[i].x.bits64[2] == e->x.i64[2]) && (S[i].x.bits64[3] == e->x.i64[3]);; 75 | if(!ok) nbWrong++; 76 | 77 | } 78 | 79 | if(items) free(items); 80 | return nbWrong; 81 | 82 | } 83 | 84 | bool Kangaroo::CheckPartition(TH_PARAM* p) { 85 | 86 | uint32_t part = p->hStart; 87 | string pName = string(p->part1Name); 88 | 89 | FILE* f1 = OpenPart(pName,"rb",part,false); 90 | if(f1 == NULL) return false; 91 | 92 | uint32_t hStart = part * (HASH_SIZE / MERGE_PART); 93 | uint32_t hStop = (part + 1) * (HASH_SIZE / MERGE_PART); 94 | p->hStart = 0; 95 | 96 | for(uint32_t h = hStart; h < hStop; h++) { 97 | 98 | uint32_t nbItem; 99 | uint32_t maxItem; 100 | ::fread(&nbItem,sizeof(uint32_t),1,f1); 101 | ::fread(&maxItem,sizeof(uint32_t),1,f1); 102 | 103 | if(nbItem == 0) 104 | continue; 105 | p->hStop += CheckHash(h,nbItem,NULL,f1); 106 | p->hStart += nbItem; 107 | 108 | } 109 | 110 | ::fclose(f1); 111 | return true; 112 | 113 | } 114 | 115 | bool Kangaroo::CheckWorkFile(TH_PARAM* p) { 116 | 117 | uint32_t nWrong = 0; 118 | 119 | for(uint32_t h = p->hStart; h < p->hStop; h++) { 120 | 121 | if(hashTable.E[h].nbItem == 0) 122 | continue; 123 | nWrong += CheckHash(h,hashTable.E[h].nbItem,&hashTable,NULL); 124 | 125 | } 126 | 127 | p->hStop = nWrong; 128 | 129 | return true; 130 | 131 | } 132 | 133 | // Threaded proc 134 | #ifdef WIN64 135 | DWORD WINAPI _checkPartThread(LPVOID lpParam) { 136 | #else 137 | void* _checkPartThread(void* lpParam) { 138 | #endif 139 | TH_PARAM* p = (TH_PARAM*)lpParam; 140 | p->obj->CheckPartition(p); 141 | p->isRunning = false; 142 | return 0; 143 | } 144 | 145 | #ifdef WIN64 146 | DWORD WINAPI _checkWorkThread(LPVOID lpParam) { 147 | #else 148 | void* _checkWorkThread(void* lpParam) { 149 | #endif 150 | TH_PARAM* p = (TH_PARAM*)lpParam; 151 | p->obj->CheckWorkFile(p); 152 | p->isRunning = false; 153 | return 0; 154 | } 155 | 156 | void Kangaroo::CheckPartition(int nbCore,std::string& partName) { 157 | 158 | double t0; 159 | double t1; 160 | uint32_t v1; 161 | 162 | t0 = Timer::get_tick(); 163 | 164 | // --------------------------------------------------- 165 | FILE* f1 = ReadHeader(partName+"/header",&v1,HEADW); 166 | if(f1 == NULL) 167 | return; 168 | 169 | uint32_t dp1; 170 | Point k1; 171 | uint64_t count1; 172 | double time1; 173 | Int RS1; 174 | Int RE1; 175 | 176 | // Read global param 177 | ::fread(&dp1,sizeof(uint32_t),1,f1); 178 | ::fread(&RS1.bits64,32,1,f1); RS1.bits64[4] = 0; 179 | ::fread(&RE1.bits64,32,1,f1); RE1.bits64[4] = 0; 180 | ::fread(&k1.x.bits64,32,1,f1); k1.x.bits64[4] = 0; 181 | ::fread(&k1.y.bits64,32,1,f1); k1.y.bits64[4] = 0; 182 | ::fread(&count1,sizeof(uint64_t),1,f1); 183 | ::fread(&time1,sizeof(double),1,f1); 184 | 185 | k1.z.SetInt32(1); 186 | if(!secp->EC(k1)) { 187 | ::printf("CheckPartition: key1 does not lie on elliptic curve\n"); 188 | ::fclose(f1); 189 | return; 190 | } 191 | 192 | ::fclose(f1); 193 | 194 | // Set starting parameters 195 | keysToSearch.clear(); 196 | keysToSearch.push_back(k1); 197 | keyIdx = 0; 198 | collisionInSameHerd = 0; 199 | rangeStart.Set(&RS1); 200 | rangeEnd.Set(&RE1); 201 | InitRange(); 202 | InitSearchKey(); 203 | 204 | int l2 = (int)log2(nbCore); 205 | int nbThread = (int)pow(2.0,l2); 206 | if(nbThread > MERGE_PART) nbThread = MERGE_PART; 207 | 208 | ::printf("Thread: %d\n",nbThread); 209 | ::printf("CheckingPart"); 210 | 211 | TH_PARAM* params = (TH_PARAM*)malloc(nbThread * sizeof(TH_PARAM)); 212 | THREAD_HANDLE* thHandles = (THREAD_HANDLE*)malloc(nbThread * sizeof(THREAD_HANDLE)); 213 | memset(params,0,nbThread * sizeof(TH_PARAM)); 214 | uint64_t nbDP = 0; 215 | uint64_t nbWrong = 0; 216 | 217 | for(int p = 0; p < MERGE_PART; p += nbThread) { 218 | 219 | printf("."); 220 | 221 | for(int i = 0; i < nbThread; i++) { 222 | params[i].threadId = i; 223 | params[i].isRunning = true; 224 | params[i].hStart = p + i; 225 | params[i].hStop = 0; 226 | params[i].part1Name = _strdup(partName.c_str()); 227 | thHandles[i] = LaunchThread(_checkPartThread,params + i); 228 | } 229 | 230 | JoinThreads(thHandles,nbThread); 231 | FreeHandles(thHandles,nbThread); 232 | 233 | for(int i = 0; i < nbThread; i++) { 234 | free(params[i].part1Name); 235 | nbDP += params[i].hStart; 236 | nbWrong += params[i].hStop; 237 | } 238 | 239 | } 240 | 241 | free(params); 242 | free(thHandles); 243 | 244 | t1 = Timer::get_tick(); 245 | 246 | double O = (double)nbWrong / (double)nbDP; 247 | O = (1.0-O) * 100.0; 248 | 249 | ::printf("[%.3f%% OK][%s]\n",O,GetTimeStr(t1 - t0).c_str()); 250 | if(nbWrong>0) { 251 | 252 | #ifdef WIN64 253 | ::printf("DP: %I64d\n",nbDP); 254 | ::printf("Wrong DP: %I64d\n",nbWrong); 255 | #else 256 | ::printf("DP: %" PRId64 "\n",nbDP); 257 | ::printf("DP Wrong: %" PRId64 "\n",nbWrong); 258 | #endif 259 | 260 | } 261 | 262 | } 263 | 264 | void Kangaroo::CheckWorkFile(int nbCore,std::string& fileName) { 265 | 266 | double t0; 267 | double t1; 268 | uint32_t v1; 269 | 270 | #ifndef WIN64 271 | setvbuf(stdout,NULL,_IONBF,0); 272 | #endif 273 | 274 | if(IsDir(fileName)) { 275 | CheckPartition(nbCore,fileName); 276 | return; 277 | } 278 | 279 | t0 = Timer::get_tick(); 280 | 281 | // --------------------------------------------------- 282 | FILE* f1 = ReadHeader(fileName,&v1,HEADW); 283 | if(f1 == NULL) 284 | return; 285 | 286 | uint32_t dp1; 287 | Point k1; 288 | uint64_t count1; 289 | double time1; 290 | Int RS1; 291 | Int RE1; 292 | 293 | // Read global param 294 | ::fread(&dp1,sizeof(uint32_t),1,f1); 295 | ::fread(&RS1.bits64,32,1,f1); RS1.bits64[4] = 0; 296 | ::fread(&RE1.bits64,32,1,f1); RE1.bits64[4] = 0; 297 | ::fread(&k1.x.bits64,32,1,f1); k1.x.bits64[4] = 0; 298 | ::fread(&k1.y.bits64,32,1,f1); k1.y.bits64[4] = 0; 299 | ::fread(&count1,sizeof(uint64_t),1,f1); 300 | ::fread(&time1,sizeof(double),1,f1); 301 | 302 | k1.z.SetInt32(1); 303 | if(!secp->EC(k1)) { 304 | ::printf("CheckWorkFile: key1 does not lie on elliptic curve\n"); 305 | ::fclose(f1); 306 | return; 307 | } 308 | 309 | // Set starting parameters 310 | keysToSearch.clear(); 311 | keysToSearch.push_back(k1); 312 | keyIdx = 0; 313 | collisionInSameHerd = 0; 314 | rangeStart.Set(&RS1); 315 | rangeEnd.Set(&RE1); 316 | InitRange(); 317 | InitSearchKey(); 318 | 319 | int l2 = (int)log2(nbCore); 320 | int nbThread = (int)pow(2.0,l2); 321 | uint64_t nbDP = 0; 322 | uint64_t nbWrong = 0; 323 | 324 | ::printf("Thread: %d\n",nbThread); 325 | ::printf("Checking"); 326 | 327 | TH_PARAM* params = (TH_PARAM*)malloc(nbThread * sizeof(TH_PARAM)); 328 | THREAD_HANDLE* thHandles = (THREAD_HANDLE*)malloc(nbThread * sizeof(THREAD_HANDLE)); 329 | memset(params,0,nbThread * sizeof(TH_PARAM)); 330 | 331 | int block = HASH_SIZE / 64; 332 | 333 | for(int s = 0; s < HASH_SIZE; s += block) { 334 | 335 | ::printf("."); 336 | 337 | uint32_t S = s; 338 | uint32_t E = s + block; 339 | 340 | // Load hashtables 341 | hashTable.LoadTable(f1,S,E); 342 | 343 | int stride = block / nbThread; 344 | 345 | for(int i = 0; i < nbThread; i++) { 346 | params[i].threadId = i; 347 | params[i].isRunning = true; 348 | params[i].hStart = S + i * stride; 349 | params[i].hStop = S + (i + 1) * stride; 350 | thHandles[i] = LaunchThread(_checkWorkThread,params + i); 351 | } 352 | JoinThreads(thHandles,nbThread); 353 | FreeHandles(thHandles,nbThread); 354 | 355 | for(int i = 0; i < nbThread; i++) 356 | nbWrong += params[i].hStop; 357 | nbDP += hashTable.GetNbItem(); 358 | 359 | hashTable.Reset(); 360 | 361 | } 362 | 363 | ::fclose(f1); 364 | free(params); 365 | free(thHandles); 366 | 367 | t1 = Timer::get_tick(); 368 | 369 | double O = (double)nbWrong / (double)nbDP; 370 | O = (1.0 - O) * 100.0; 371 | 372 | ::printf("[%.3f%% OK][%s]\n",O,GetTimeStr(t1 - t0).c_str()); 373 | if(nbWrong > 0) { 374 | 375 | #ifdef WIN64 376 | ::printf("DP: %I64d\n",nbDP); 377 | ::printf("Wrong DP: %I64d\n",nbWrong); 378 | #else 379 | ::printf("DP: %" PRId64 "\n",nbDP); 380 | ::printf("DP Wrong: %" PRId64 "\n",nbWrong); 381 | #endif 382 | 383 | } 384 | 385 | } 386 | 387 | 388 | void Kangaroo::Check(std::vector gpuId,std::vector gridSize) { 389 | 390 | Int::Check(); 391 | 392 | initDPSize = 8; 393 | SetDP(initDPSize); 394 | 395 | double t0; 396 | double t1; 397 | int nbKey = 16384; 398 | vector pts1; 399 | vector pts2; 400 | vector priv; 401 | 402 | // Check on ComputePublicKeys 403 | for(int i = 0; iComputePublicKey(&priv[i])); 412 | t1 = Timer::get_tick(); 413 | ::printf("ComputePublicKey %d : %.3f KKey/s\n",nbKey,(double)nbKey / ((t1 - t0)*1000.0)); 414 | 415 | t0 = Timer::get_tick(); 416 | pts2 = secp->ComputePublicKeys(priv); 417 | t1 = Timer::get_tick(); 418 | ::printf("ComputePublicKeys %d : %.3f KKey/s\n",nbKey,(double)nbKey / ((t1 - t0)*1000.0)); 419 | 420 | bool ok = true; 421 | int i = 0; 422 | for(; ok && iComputePublicKey(&k1); 452 | CreateJumpTable(); 453 | keysToSearch.clear(); 454 | keysToSearch.push_back(P); 455 | keyIdx = 0; 456 | InitRange(); 457 | InitSearchKey(); 458 | 459 | ::printf("GPU allocate memory:"); 460 | int x = gridSize[0]; 461 | int y = gridSize[1]; 462 | if(!GPUEngine::GetGridSize(gpuId[0],&x,&y)) { 463 | return; 464 | } 465 | 466 | GPUEngine h(x,y,gpuId[0],65536); 467 | ::printf(" done\n"); 468 | ::printf("GPU: %s\n",h.deviceName.c_str()); 469 | ::printf("GPU: %.1f MB\n",h.GetMemory() / 1048576.0); 470 | 471 | int nb = h.GetNbThread() * GPU_GRP_SIZE; 472 | 473 | Int *gpuPx = new Int[nb]; 474 | Int *gpuPy = new Int[nb]; 475 | Int *gpuD = new Int[nb]; 476 | Int *cpuPx = new Int[nb]; 477 | Int *cpuPy = new Int[nb]; 478 | Int *cpuD = new Int[nb]; 479 | uint64_t *lastJump = new uint64_t[nb]; 480 | vector gpuFound; 481 | 482 | Int pk; 483 | pk.Rand(256); 484 | keyToSearch = secp->ComputePublicKey(&pk); 485 | 486 | CreateHerd(nb,cpuPx,cpuPy,cpuD,TAME); 487 | for(int i=0;iAddDirect(P,J); 522 | cpuPx[i].Set(&P.x); 523 | cpuPy[i].Set(&P.y); 524 | 525 | cpuD[i].ModAddK1order(&jumpDistance[jmp]); 526 | 527 | #ifdef USE_SYMMETRY 528 | // Equivalence symmetry class switch 529 | if(cpuPy[i].ModPositiveK1()) 530 | cpuD[i].ModNegK1order(); 531 | lastJump[i] = jmp; 532 | #endif 533 | 534 | if(IsDP(&cpuPx[i])) { 535 | 536 | // Search for DP found 537 | bool found = false; 538 | int j = 0; 539 | while(!found && j<(int)gpuFound.size()) { 540 | found = gpuFound[j].x.IsEqual(&cpuPx[i]) && 541 | gpuFound[j].d.IsEqual(&cpuD[i]) && 542 | gpuFound[j].kIdx == (uint64_t)i; 543 | if(!found) j++; 544 | } 545 | 546 | if(found) { 547 | gpuFound.erase(gpuFound.begin() + j); 548 | } else { 549 | ::printf("DP Mismatch:\n"); 550 | #ifdef WIN64 551 | ::printf("[%d] %s [0x%016I64X]\n",j,gpuFound[j].x.GetBase16().c_str(),gpuFound[j].kIdx); 552 | #else 553 | ::printf("[%d] %s [0x%" PRIx64 "]\n",j,gpuFound[j].x.GetBase16().c_str(),gpuFound[j].kIdx); 554 | #endif 555 | ::printf("[%d] %s \n",i,cpuPx[gpuFound[i].kIdx].GetBase16().c_str()); 556 | return; 557 | } 558 | 559 | } 560 | 561 | } 562 | } 563 | 564 | // Compare kangaroos 565 | int nbFault = 0; 566 | bool firstFaut = true; 567 | for(int i = 0; i 6 | #include "../Constants.h" 7 | #include "../SECPK1/SECP256k1.h" 8 | 9 | #ifdef USE_SYMMETRY 10 | #define KSIZE 11 11 | #else 12 | #define KSIZE 10 13 | #endif 14 | 15 | #define ITEM_SIZE 56 16 | #define ITEM_SIZE32 (ITEM_SIZE/4) 17 | 18 | typedef struct { 19 | Int x; 20 | Int d; 21 | uint64_t kIdx; // Appears like this is used as kType 22 | uint64_t h; 23 | } ITEM; 24 | 25 | class GPUEngine { 26 | 27 | public: 28 | 29 | GPUEngine(int nbThreadGroup,int nbThreadPerGroup,int gpuId,uint32_t maxFound); 30 | ~GPUEngine(); 31 | void SetParams(Int *dpMask,Int *distance,Int *px,Int *py); 32 | void SetKangaroos(Int *px,Int *py,Int *d); 33 | void GetKangaroos(Int *px,Int *py,Int *d); 34 | void SetKangaroo(uint64_t kIdx, Int *px,Int *py,Int *d); 35 | bool Launch(std::vector &hashFound,bool spinWait = false); 36 | void SetWildOffset(Int *offset); 37 | int GetNbThread(); 38 | int GetGroupSize(); 39 | int GetMemory(); 40 | bool callKernelAndWait(); 41 | bool callKernel(); 42 | 43 | std::string deviceName; 44 | 45 | static void *AllocatePinnedMemory(size_t size); 46 | static void FreePinnedMemory(void *buff); 47 | static void PrintCudaInfo(); 48 | static bool GetGridSize(int gpuId,int *x,int *y); 49 | 50 | private: 51 | 52 | Int wildOffset; 53 | int nbThread; 54 | int nbThreadPerGroup; 55 | uint64_t *inputKangaroo; 56 | uint64_t *inputKangarooPinned; 57 | uint32_t *outputItem; 58 | uint32_t *outputItemPinned; 59 | uint64_t *jumpPinned; 60 | bool initialised; 61 | bool lostWarning; 62 | uint32_t maxFound; 63 | uint32_t outputSize; 64 | uint32_t kangarooSize; 65 | uint32_t kangarooSizePinned; 66 | uint32_t jumpSize; 67 | uint64_t *dpMask; 68 | }; 69 | 70 | #endif // GPUENGINEH 71 | -------------------------------------------------------------------------------- /GPU/GPUGenerate.cpp: -------------------------------------------------------------------------------- 1 | #include "GPUEngine.h" 2 | #include 3 | 4 | using namespace std; 5 | 6 | 7 | void GPUEngine::GenerateCode(Secp256K1 *secp) { 8 | 9 | // Compute generator table 10 | Int jumpDistance[257]; 11 | Point jumpPoint[257]; 12 | 13 | // Kangaroo jumps 14 | jumpPoint[0] = secp->G; 15 | jumpDistance[0].SetInt32(1); 16 | for(int i = 1; i < 257; ++i) { 17 | jumpDistance[i].Add(&jumpDistance[i - 1],&jumpDistance[i - 1]); 18 | jumpPoint[i] = secp->DoubleDirect(jumpPoint[i - 1]); 19 | } 20 | 21 | // Write file 22 | FILE *f = fopen("../GPU/GPUGroup.h","w"); 23 | 24 | fprintf(f,"// File generated by GPUEngine::GenerateCode()\n"); 25 | 26 | fprintf(f,"// Jump distance table (Contains 1,2,4,...,2^257\n"); 27 | fprintf(f,"__device__ __constant__ uint64_t jD[][4] = {\n"); 28 | for(int i = 0; i < 257; i++) { 29 | fprintf(f," %s,\n",jumpDistance[i].GetC64Str(4).c_str()); 30 | } 31 | fprintf(f,"};\n"); 32 | 33 | fprintf(f,"// Jump point table (Contains G,2G,4G,...,2^257.G)\n"); 34 | fprintf(f,"__device__ __constant__ uint64_t jPx[][4] = {\n"); 35 | for(int i = 0; i < 257; i++) { 36 | fprintf(f," %s,\n",jumpPoint[i].x.GetC64Str(4).c_str()); 37 | } 38 | fprintf(f,"};\n"); 39 | 40 | fprintf(f,"__device__ __constant__ uint64_t jPy[][4] = {\n"); 41 | for(int i = 0; i < 257; i++) { 42 | fprintf(f," %s,\n",jumpPoint[i].y.GetC64Str(4).c_str()); 43 | } 44 | fprintf(f,"};\n\n"); 45 | 46 | fclose(f); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /HashTable.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "HashTable.h" 3 | #include 4 | #include 5 | #ifndef WIN64 6 | #include 7 | #endif 8 | 9 | #define GET(hash,id) E[hash].items[id] 10 | 11 | HashTable::HashTable() { 12 | 13 | memset(E,0,sizeof(E)); 14 | 15 | } 16 | 17 | void HashTable::Reset() { 18 | 19 | for(uint32_t h = 0; h < HASH_SIZE; h++) { 20 | if(E[h].items) { 21 | for(uint32_t i = 0; ix.i64[0] = x->i64[0]; 45 | e->x.i64[1] = x->i64[1]; 46 | e->x.i64[2] = x->i64[2]; 47 | e->x.i64[3] = x->i64[3]; 48 | e->d.i64[0] = d->i64[0]; 49 | e->d.i64[1] = d->i64[1]; 50 | e->d.i64[2] = d->i64[2]; 51 | e->d.i64[3] = d->i64[3]; 52 | e->kType = kType; 53 | 54 | return e; 55 | 56 | } 57 | 58 | #define ADD_ENTRY(entry) { \ 59 | /* Shift the end of the index table */ \ 60 | for (int i = E[h].nbItem; i > st; i--) \ 61 | E[h].items[i] = E[h].items[i - 1]; \ 62 | E[h].items[st] = entry; \ 63 | E[h].nbItem++;} 64 | 65 | void HashTable::toint256t(Int *a, int256_t *b) 66 | { 67 | b->i64[0] = a->bits64[0]; 68 | b->i64[1] = a->bits64[1]; 69 | b->i64[2] = a->bits64[2]; 70 | b->i64[3] = a->bits64[3]; 71 | } 72 | 73 | void HashTable::toInt(int256_t *a, Int *b) 74 | { 75 | b->bits64[0] = a->i64[0]; 76 | b->bits64[1] = a->i64[1]; 77 | b->bits64[2] = a->i64[2]; 78 | b->bits64[3] = a->i64[3]; 79 | } 80 | 81 | void HashTable::Convert(Int *x,Int *d,int256_t *X,int256_t *D) { 82 | 83 | toint256t(x,X); 84 | toint256t(d,D); 85 | } 86 | 87 | 88 | #define AV1() if(pnb1) { ::fread(&e1,32,1,f1); pnb1--; } 89 | #define AV2() if(pnb2) { ::fread(&e2,32,1,f2); pnb2--; } 90 | 91 | int HashTable::MergeH(uint32_t h,FILE* f1,FILE* f2,FILE* fd,uint32_t* nbDP,uint32_t *duplicate,Int* d1,uint32_t* k1,Int* d2,uint32_t* k2) { 92 | 93 | // Merge by line 94 | // N comparison but avoid slow item allocation 95 | // return ADD_OK or ADD_COLLISION if a COLLISION is detected 96 | 97 | uint32_t nb1; 98 | uint32_t m1; 99 | uint32_t nb2; 100 | uint32_t m2; 101 | *duplicate = 0; 102 | *nbDP = 0; 103 | 104 | ::fread(&nb1,sizeof(uint32_t),1,f1); 105 | ::fread(&m1,sizeof(uint32_t),1,f1); 106 | ::fread(&nb2,sizeof(uint32_t),1,f2); 107 | ::fread(&m2,sizeof(uint32_t),1,f2); 108 | 109 | // Maximum in destination 110 | uint32_t nbd = 0; 111 | uint32_t md = nb1 + nb2; 112 | 113 | if(md==0) { 114 | 115 | ::fwrite(&md,sizeof(uint32_t),1,fd); 116 | ::fwrite(&md,sizeof(uint32_t),1,fd); 117 | return ADD_OK; 118 | 119 | } 120 | 121 | ENTRY *output = (ENTRY *)malloc( md * sizeof(ENTRY) ); 122 | 123 | ENTRY e1; 124 | ENTRY e2; 125 | 126 | uint32_t pnb1 = nb1; 127 | uint32_t pnb2 = nb2; 128 | AV1(); 129 | AV2(); 130 | bool end1 = (nb1 == 0); 131 | bool end2 = (nb2 == 0); 132 | bool collisionFound = false; 133 | 134 | while(!(end1 && end2)) { 135 | 136 | if( !end1 && !end2 ) { 137 | 138 | int comp = compare(&e1.x,&e2.x); 139 | if(comp < 0) { 140 | memcpy(output+nbd,&e1,32); 141 | nbd++; 142 | AV1(); 143 | nb1--; 144 | } else if (comp==0) { 145 | if((e1.d.i64[0] == e2.d.i64[0]) && (e1.d.i64[1] == e2.d.i64[1]) && (e1.d.i64[2] == e2.d.i64[2]) && (e1.d.i64[3] == e2.d.i64[3])) { 146 | *duplicate = *duplicate + 1; 147 | } else { 148 | // Collision 149 | *k1 = e1.kType; 150 | *k2 = e2.kType; 151 | CalcDist(&(e1.d),d1); 152 | CalcDist(&(e2.d),d2); 153 | collisionFound = true; 154 | } 155 | memcpy(output + nbd,&e1,32); 156 | nbd++; 157 | AV1(); 158 | AV2(); 159 | nb1--; 160 | nb2--; 161 | } else { 162 | memcpy(output + nbd,&e2,32); 163 | nbd++; 164 | AV2(); 165 | nb2--; 166 | } 167 | 168 | } else if( !end1 && end2 ) { 169 | 170 | memcpy(output + nbd,&e1,32); 171 | nbd++; 172 | AV1(); 173 | nb1--; 174 | 175 | } else if( end1 && !end2) { 176 | 177 | memcpy(output + nbd,&e2,32); 178 | nbd++; 179 | AV2(); 180 | nb2--; 181 | 182 | } 183 | 184 | end1 = (nb1 == 0); 185 | end2 = (nb2 == 0); 186 | 187 | } 188 | 189 | // write output 190 | 191 | // Round md to next multiple of 4 192 | if(nbd%4==0) { 193 | md = nbd; 194 | } else { 195 | md = ((nbd/4)+1)*4; 196 | } 197 | 198 | ::fwrite(&nbd,sizeof(uint32_t),1,fd); 199 | ::fwrite(&md,sizeof(uint32_t),1,fd); 200 | ::fwrite(output,32,nbd,fd); 201 | free(output); 202 | 203 | *nbDP = nbd; 204 | return (collisionFound?ADD_COLLISION:ADD_OK); 205 | 206 | } 207 | 208 | int HashTable::Add(Int *x,Int *d,uint32_t type) { 209 | 210 | int256_t X; 211 | int256_t D; 212 | Convert(x,d,&X,&D); 213 | uint64_t h = (x->bits64[0] ^ x->bits64[1] ^ x->bits64[2] ^ x->bits64[3]) % HASH_SIZE; 214 | ENTRY* e = CreateEntry(&X,&D,type); 215 | return Add(h,e); 216 | 217 | } 218 | 219 | void HashTable::ReAllocate(uint64_t h,uint32_t add) { 220 | 221 | E[h].maxItem += add; 222 | ENTRY** nitems = (ENTRY**)malloc(sizeof(ENTRY*) * E[h].maxItem); 223 | memcpy(nitems,E[h].items,sizeof(ENTRY*) * E[h].nbItem); 224 | free(E[h].items); 225 | E[h].items = nitems; 226 | 227 | } 228 | 229 | int HashTable::Add(int256_t *x,int256_t *d, uint32_t type) { 230 | uint64_t h = (x->i64[0] ^ x->i64[1] ^ x->i64[2] ^ x->i64[3]) & HASH_SIZE; 231 | ENTRY *e = CreateEntry(x,d,type); 232 | return Add(h,e); 233 | 234 | } 235 | 236 | void HashTable::CalcDist(int256_t *d,Int* kDist) { 237 | kDist->SetInt32(0); 238 | toInt(d,kDist); 239 | } 240 | 241 | int HashTable::Add(uint64_t h,ENTRY* e) { 242 | if(E[h].maxItem == 0) { 243 | E[h].maxItem = 16; 244 | E[h].items = (ENTRY **)malloc(sizeof(ENTRY *) * E[h].maxItem); 245 | } 246 | 247 | if(E[h].nbItem == 0) { 248 | E[h].items[0] = e; 249 | E[h].nbItem = 1; 250 | return ADD_OK; 251 | } 252 | 253 | if(E[h].nbItem >= E[h].maxItem - 1) { 254 | // We need to reallocate 255 | ReAllocate(h,4); 256 | } 257 | 258 | // Search insertion position 259 | int st,ed,mi; 260 | st = 0; ed = E[h].nbItem - 1; 261 | while(st <= ed) { 262 | mi = (st + ed) / 2; 263 | int comp = compare(&e->x,&GET(h,mi)->x); 264 | if(comp<0) { 265 | ed = mi - 1; 266 | } else if (comp==0) { 267 | ENTRY *ent = GET(h,mi); 268 | uint64_t d10 = e->d.i64[0]; 269 | uint64_t d11 = e->d.i64[1]; 270 | uint64_t d12 = e->d.i64[2]; 271 | uint64_t d13 = e->d.i64[3]; 272 | uint64_t d20 = ent->d.i64[0]; 273 | uint64_t d21 = ent->d.i64[1]; 274 | uint64_t d22 = ent->d.i64[2]; 275 | uint64_t d23 = ent->d.i64[3]; 276 | if (d10 == d20 && d11 == d21 && d12 == d22 || d13 == d23) { 277 | // Same point added twice or collision in the same herd! 278 | return ADD_DUPLICATE; 279 | } 280 | // Collision 281 | kType = ent->kType; 282 | CalcDist(&(ent->d), &kDist); 283 | return ADD_COLLISION; 284 | 285 | } else { 286 | st = mi + 1; 287 | } 288 | } 289 | 290 | ADD_ENTRY(e); 291 | return ADD_OK; 292 | 293 | } 294 | 295 | int HashTable::compare(int256_t *i1,int256_t *i2) { 296 | 297 | uint64_t *a = i1->i64; 298 | uint64_t *b = i2->i64; 299 | 300 | if(a[3] == b[3]) { 301 | if(a[2] == b[2]) { 302 | if(a[1] == b[1]) { 303 | if(a[0] == b[0]) { 304 | return 0; 305 | } else { 306 | return (a[0] > b[0]) ? 1 : -1; 307 | } 308 | } else { 309 | return (a[1] > b[1]) ? 1 : -1; 310 | } 311 | } else { 312 | return (a[2] > b[2]) ? 1 : -1; 313 | } 314 | } else { 315 | return (a[3] > b[3]) ? 1 : -1; 316 | } 317 | 318 | } 319 | 320 | std::string HashTable::GetSizeInfo() { 321 | 322 | char *unit; 323 | uint64_t totalByte = sizeof(E); 324 | uint64_t usedByte = HASH_SIZE*2*sizeof(uint32_t); 325 | 326 | for (int h = 0; h < HASH_SIZE; h++) { 327 | totalByte += sizeof(ENTRY *) * E[h].maxItem; 328 | totalByte += sizeof(ENTRY) * E[h].nbItem; 329 | usedByte += sizeof(ENTRY) * E[h].nbItem; 330 | } 331 | 332 | unit = "MB"; 333 | double totalMB = (double)totalByte / (1024.0*1024.0); 334 | double usedMB = (double)usedByte / (1024.0*1024.0); 335 | if(totalMB > 1024) { 336 | totalMB /= 1024; 337 | usedMB /= 1024; 338 | unit = "GB"; 339 | } 340 | if(totalMB > 1024) { 341 | totalMB /= 1024; 342 | usedMB /= 1024; 343 | unit = "TB"; 344 | } 345 | 346 | char ret[256]; 347 | sprintf(ret,"%.1f/%.1f%s",usedMB,totalMB,unit); 348 | 349 | return std::string(ret); 350 | 351 | } 352 | 353 | std::string HashTable::GetStr(int256_t *i) { 354 | 355 | std::string ret; 356 | char tmp[256]; 357 | for(int n=3;n>=0;n--) { 358 | ::sprintf(tmp,"%08X",i->i32[n]); 359 | ret += std::string(tmp); 360 | } 361 | return ret; 362 | 363 | } 364 | 365 | void HashTable::SaveTable(FILE* f) { 366 | SaveTable(f,0,HASH_SIZE,true); 367 | } 368 | 369 | void HashTable::SaveTable(FILE* f,uint32_t from,uint32_t to,bool printPoint) { 370 | 371 | uint64_t point = GetNbItem() / 16; 372 | uint64_t pointPrint = 0; 373 | 374 | for(uint32_t h = from; h < to; h++) { 375 | fwrite(&E[h].nbItem,sizeof(uint32_t),1,f); 376 | fwrite(&E[h].maxItem,sizeof(uint32_t),1,f); 377 | for(uint32_t i = 0; i < E[h].nbItem; i++) { 378 | fwrite(&(E[h].items[i]->x),32,1,f); 379 | fwrite(&(E[h].items[i]->d),32,1,f); 380 | fwrite(&(E[h].items[i]->kType),4,1,f); 381 | if(printPoint) { 382 | pointPrint++; 383 | if(pointPrint > point) { 384 | ::printf("."); 385 | pointPrint = 0; 386 | } 387 | } 388 | } 389 | } 390 | 391 | } 392 | 393 | void HashTable::SeekNbItem(FILE* f,bool restorePos) { 394 | 395 | Reset(); 396 | 397 | #ifdef WIN64 398 | uint64_t org = (uint64_t)_ftelli64(f); 399 | #else 400 | uint64_t org = (uint64_t)ftello(f); 401 | #endif 402 | 403 | SeekNbItem(f,0,HASH_SIZE); 404 | 405 | if( restorePos ) { 406 | // Restore position 407 | #ifdef WIN64 408 | _fseeki64(f,org,SEEK_SET); 409 | #else 410 | fseeko(f,org,SEEK_SET); 411 | #endif 412 | } 413 | 414 | } 415 | 416 | void HashTable::SeekNbItem(FILE* f,uint32_t from,uint32_t to) { 417 | 418 | for(uint32_t h = from; h < to; h++) { 419 | 420 | fread(&E[h].nbItem,sizeof(uint32_t),1,f); 421 | fread(&E[h].maxItem,sizeof(uint32_t),1,f); 422 | 423 | uint64_t hSize = 32ULL * E[h].nbItem; 424 | #ifdef WIN64 425 | _fseeki64(f,hSize,SEEK_CUR); 426 | #else 427 | fseeko(f,hSize,SEEK_CUR); 428 | #endif 429 | 430 | } 431 | 432 | } 433 | 434 | void HashTable::LoadTable(FILE* f,uint32_t from,uint32_t to) { 435 | 436 | Reset(); 437 | 438 | for(uint32_t h = from; h < to; h++) { 439 | 440 | fread(&E[h].nbItem,sizeof(uint32_t),1,f); 441 | fread(&E[h].maxItem,sizeof(uint32_t),1,f); 442 | 443 | if(E[h].maxItem > 0) 444 | // Allocate indexes 445 | E[h].items = (ENTRY**)malloc(sizeof(ENTRY*) * E[h].maxItem); 446 | 447 | for(uint32_t i = 0; i < E[h].nbItem; i++) { 448 | ENTRY* e = (ENTRY*)malloc(sizeof(ENTRY)); 449 | fread(&(e->x),32,1,f); 450 | fread(&(e->d),32,1,f); 451 | fread(&(e->kType),4,1,f); 452 | E[h].items[i] = e; 453 | } 454 | 455 | } 456 | 457 | 458 | } 459 | 460 | void HashTable::LoadTable(FILE *f) { 461 | 462 | LoadTable(f,0,HASH_SIZE); 463 | 464 | } 465 | 466 | void HashTable::PrintInfo() { 467 | 468 | uint16_t max = 0; 469 | uint32_t maxH = 0; 470 | uint16_t min = 65535; 471 | uint32_t minH = 0; 472 | double std = 0; 473 | double avg = (double)GetNbItem() / (double)HASH_SIZE; 474 | 475 | for(uint32_t h=0;hmax) { 477 | max= E[h].nbItem; 478 | maxH = h; 479 | } 480 | if(E[h].nbItemx).c_str()); 504 | // ::printf("[%2d] %s\n",i,GetStr(&E[maxH].items[i]->d).c_str()); 505 | //} 506 | 507 | } 508 | -------------------------------------------------------------------------------- /HashTable.h: -------------------------------------------------------------------------------- 1 | #ifndef HASHTABLEH 2 | #define HASHTABLEH 3 | 4 | #include 5 | #include 6 | #include "SECPK1/Point.h" 7 | #include "Constants.h" 8 | #ifdef WIN64 9 | #include 10 | #endif 11 | 12 | #define HASH_SIZE_BIT 18 13 | #define HASH_SIZE (1< 7 | #include 8 | #else 9 | typedef int SOCKET; 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #endif 21 | 22 | #include 23 | #include 24 | #include "SECPK1/SECP256k1.h" 25 | #include "HashTable.h" 26 | #include "SECPK1/IntGroup.h" 27 | #include "GPU/GPUEngine.h" 28 | 29 | #ifdef WIN64 30 | typedef HANDLE THREAD_HANDLE; 31 | #define LOCK(mutex) WaitForSingleObject(mutex,INFINITE); 32 | #define UNLOCK(mutex) ReleaseMutex(mutex); 33 | #else 34 | typedef pthread_t THREAD_HANDLE; 35 | #define LOCK(mutex) pthread_mutex_lock(&(mutex)); 36 | #define UNLOCK(mutex) pthread_mutex_unlock(&(mutex)); 37 | #endif 38 | 39 | class Kangaroo; 40 | 41 | // Input thread parameters 42 | typedef struct { 43 | 44 | Kangaroo *obj; 45 | int threadId; 46 | bool isRunning; 47 | bool hasStarted; 48 | bool isWaiting; 49 | uint64_t nbKangaroo; 50 | 51 | #ifdef WITHGPU 52 | int gridSizeX; 53 | int gridSizeY; 54 | int gpuId; 55 | #endif 56 | 57 | Int *px; // Kangaroo position 58 | Int *py; // Kangaroo position 59 | Int *distance; // Travelled distance 60 | #ifdef USE_SYMMETRY 61 | uint64_t *symClass; // Last jump 62 | #endif 63 | 64 | SOCKET clientSock; 65 | char *clientInfo; 66 | 67 | uint32_t hStart; 68 | uint32_t hStop; 69 | char *part1Name; 70 | char *part2Name; 71 | 72 | } TH_PARAM; 73 | 74 | 75 | // DP transfered over the network 76 | typedef struct { 77 | 78 | uint32_t kIdx; 79 | int256_t x; 80 | int256_t d; 81 | 82 | } DP; 83 | 84 | typedef struct { 85 | 86 | uint32_t header; 87 | uint32_t nbDP; 88 | uint32_t threadId; 89 | uint32_t processId; 90 | uint32_t gpuId; 91 | 92 | } DPHEADER; 93 | 94 | // DP cache 95 | typedef struct { 96 | uint32_t nbDP; 97 | DP *dp; 98 | } DP_CACHE; 99 | 100 | // Work file type 101 | #define HEADW 0xFA6A8001 // Full work file 102 | #define HEADK 0xFA6A8002 // Kangaroo only file 103 | #define HEADKS 0xFA6A8003 // Compressed Kangaroo only file 104 | 105 | // Number of Hash entry per partition 106 | #define H_PER_PART (HASH_SIZE / MERGE_PART) 107 | 108 | class Kangaroo { 109 | 110 | public: 111 | 112 | Kangaroo(Secp256K1 *secp,int32_t initDPSize,bool useGpu,std::string &workFile,std::string &iWorkFile, 113 | uint32_t savePeriod,bool saveKangaroo,bool saveKangarooByServer,double maxStep,int wtimeout,int sport,int ntimeout, 114 | std::string serverIp,std::string outputFile,bool splitWorkfile); 115 | void Run(int nbThread,std::vector gpuId,std::vector gridSize); 116 | void RunServer(); 117 | bool ParseConfigFile(std::string &fileName); 118 | bool LoadWork(std::string &fileName); 119 | void Check(std::vector gpuId,std::vector gridSize); 120 | void MergeDir(std::string& dirname,std::string& dest); 121 | bool MergeWork(std::string &file1,std::string &file2,std::string &dest,bool printStat=true); 122 | void WorkInfo(std::string &fileName); 123 | bool MergeWorkPart(std::string& file1,std::string& file2,bool printStat); 124 | bool MergeWorkPartPart(std::string& part1Name,std::string& part2Name); 125 | static void CreateEmptyPartWork(std::string& partName); 126 | void CheckWorkFile(int nbCore,std::string& fileName); 127 | void CheckPartition(int nbCore,std::string& partName); 128 | bool FillEmptyPartFromFile(std::string& partName,std::string& fileName,bool printStat); 129 | 130 | // Threaded procedures 131 | void SolveKeyCPU(TH_PARAM *p); 132 | void SolveKeyGPU(TH_PARAM *p); 133 | bool HandleRequest(TH_PARAM *p); 134 | bool MergePartition(TH_PARAM* p); 135 | bool CheckPartition(TH_PARAM* p); 136 | bool CheckWorkFile(TH_PARAM* p); 137 | void ProcessServer(); 138 | 139 | void AddConnectedClient(); 140 | void RemoveConnectedClient(); 141 | void RemoveConnectedKangaroo(uint64_t nb); 142 | 143 | private: 144 | 145 | bool IsDP(Int *x); 146 | void SetDP(int size); 147 | void CreateHerd(int nbKangaroo,Int *px, Int *py, Int *d, int firstType,bool lock=true); 148 | void CreateJumpTable(); 149 | bool AddToTable(uint64_t h,int256_t *x,int256_t *d); 150 | bool AddToTable(int256_t *x,int256_t *d, uint32_t kType); 151 | bool AddToTable(uint64_t h, int256_t *x,int256_t *d, uint32_t kType); 152 | bool AddToTable(Int *pos,Int *dist, uint32_t kType); 153 | bool SendToServer(std::vector &dp,uint32_t threadId,uint32_t gpuId); 154 | bool CheckKey(Int d1,Int d2,uint8_t type); 155 | bool CollisionCheck(Int* d1, uint32_t type1,Int* d2, uint32_t type2); 156 | void ComputeExpected(double dp,double *op,double *ram,double* overHead = NULL); 157 | void InitRange(); 158 | void InitSearchKey(); 159 | std::string GetTimeStr(double s); 160 | bool Output(Int* pk,char sInfo,int sType); 161 | 162 | // Backup stuff 163 | void SaveWork(std::string fileName,FILE *f,int type,uint64_t totalCount,double totalTime); 164 | void SaveWork(uint64_t totalCount,double totalTime,TH_PARAM *threads,int nbThread); 165 | void SaveServerWork(); 166 | void FetchWalks(uint64_t nbWalk,Int *x,Int *y,Int *d); 167 | void FetchWalks(uint64_t nbWalk,std::vector& kangs,Int* x,Int* y,Int* d); 168 | void FectchKangaroos(TH_PARAM *threads); 169 | FILE *ReadHeader(std::string fileName,uint32_t *version,int type); 170 | bool SaveHeader(std::string fileName,FILE* f,int type,uint64_t totalCount,double totalTime); 171 | int FSeek(FILE *stream,uint64_t pos); 172 | uint64_t FTell(FILE *stream); 173 | int IsDir(std::string dirName); 174 | bool IsEmpty(std::string fileName); 175 | static std::string GetPartName(std::string& partName,int i,bool tmpPart); 176 | static FILE* OpenPart(std::string& partName,char* mode,int i,bool tmpPart=false); 177 | uint32_t CheckHash(uint32_t h,uint32_t nbItem,HashTable* hT,FILE* f); 178 | 179 | 180 | // Network stuff 181 | void AcceptConnections(SOCKET server_soc); 182 | int WaitFor(SOCKET sock,int timeout,int mode); 183 | int Write(SOCKET sock,char *buf,int bufsize,int timeout); 184 | int Read(SOCKET sock,char *buf,int bufsize,int timeout); 185 | bool GetConfigFromServer(); 186 | bool ConnectToServer(SOCKET *retSock); 187 | void InitSocket(); 188 | void WaitForServer(); 189 | int32_t GetServerStatus(); 190 | bool SendKangaroosToServer(std::string& fileName,std::vector& kangs); 191 | bool GetKangaroosFromServer(std::string& fileName,std::vector& kangs); 192 | 193 | #ifdef WIN64 194 | HANDLE ghMutex; 195 | HANDLE saveMutex; 196 | THREAD_HANDLE LaunchThread(LPTHREAD_START_ROUTINE func,TH_PARAM *p); 197 | #else 198 | pthread_mutex_t ghMutex; 199 | pthread_mutex_t saveMutex; 200 | THREAD_HANDLE LaunchThread(void *(*func) (void *), TH_PARAM *p); 201 | #endif 202 | 203 | void JoinThreads(THREAD_HANDLE *handles, int nbThread); 204 | void FreeHandles(THREAD_HANDLE *handles, int nbThread); 205 | void Process(TH_PARAM *params,std::string unit); 206 | 207 | uint64_t getCPUCount(); 208 | uint64_t getGPUCount(); 209 | bool isAlive(TH_PARAM *p); 210 | bool hasStarted(TH_PARAM *p); 211 | bool isWaiting(TH_PARAM *p); 212 | 213 | Secp256K1 *secp; 214 | HashTable hashTable; 215 | uint64_t counters[256]; 216 | int nbCPUThread; 217 | int nbGPUThread; 218 | double startTime; 219 | 220 | // Range 221 | int rangePower; 222 | Int rangeStart; 223 | Int rangeEnd; 224 | Int rangeWidth; 225 | Int rangeWidthDiv2; 226 | Int rangeWidthDiv4; 227 | Int rangeWidthDiv8; 228 | 229 | int256_t dMask; 230 | uint32_t dpSize; 231 | int32_t initDPSize; 232 | uint64_t collisionInSameHerd; 233 | std::vector keysToSearch; 234 | Point keyToSearch; 235 | Point keyToSearchNeg; 236 | uint32_t keyIdx; 237 | bool endOfSearch; 238 | bool useGpu; 239 | double expectedNbOp; 240 | double expectedMem; 241 | double maxStep; 242 | uint64_t totalRW; 243 | 244 | Int jumpDistance[NB_JUMP]; 245 | Int jumpPointx[NB_JUMP]; 246 | Int jumpPointy[NB_JUMP]; 247 | 248 | int CPU_GRP_SIZE; 249 | 250 | // Backup stuff 251 | std::string outputFile; 252 | FILE *fRead; 253 | uint64_t offsetCount; 254 | double offsetTime; 255 | int64_t nbLoadedWalk; 256 | std::string workFile; 257 | std::string inputFile; 258 | int saveWorkPeriod; 259 | bool saveRequest; 260 | bool saveKangaroo; 261 | bool saveKangarooByServer; 262 | int wtimeout; 263 | int ntimeout; 264 | bool splitWorkfile; 265 | 266 | // Network stuff 267 | int port; 268 | std::string lastError; 269 | std::string serverIp; 270 | char *hostInfo; 271 | int hostInfoLength; 272 | int hostAddrType; 273 | bool clientMode; 274 | bool isConnected; 275 | SOCKET serverConn; 276 | std::vector recvDP; 277 | std::vector localCache; 278 | std::string serverStatus; 279 | int connectedClient; 280 | uint32_t pid; 281 | 282 | }; 283 | 284 | #endif // KANGAROOH 285 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ifdef gpu 2 | 3 | SRC = SECPK1/IntGroup.cpp main.cpp SECPK1/Random.cpp \ 4 | Timer.cpp SECPK1/Int.cpp SECPK1/IntMod.cpp \ 5 | SECPK1/Point.cpp SECPK1/SECP256K1.cpp \ 6 | GPU/GPUEngine.o Kangaroo.cpp HashTable.cpp \ 7 | Backup.cpp Thread.cpp Check.cpp Network.cpp Merge.cpp PartMerge.cpp 8 | 9 | OBJDIR = obj 10 | 11 | OBJET = $(addprefix $(OBJDIR)/, \ 12 | SECPK1/IntGroup.o main.o SECPK1/Random.o \ 13 | Timer.o SECPK1/Int.o SECPK1/IntMod.o \ 14 | SECPK1/Point.o SECPK1/SECP256K1.o \ 15 | GPU/GPUEngine.o Kangaroo.o HashTable.o Thread.o \ 16 | Backup.o Check.o Network.o Merge.o PartMerge.o) 17 | 18 | else 19 | 20 | SRC = SECPK1/IntGroup.cpp main.cpp SECPK1/Random.cpp \ 21 | Timer.cpp SECPK1/Int.cpp SECPK1/IntMod.cpp \ 22 | SECPK1/Point.cpp SECPK1/SECP256K1.cpp \ 23 | Kangaroo.cpp HashTable.cpp Thread.cpp Check.cpp \ 24 | Backup.cpp Network.cpp Merge.cpp PartMerge.cpp 25 | 26 | OBJDIR = obj 27 | 28 | OBJET = $(addprefix $(OBJDIR)/, \ 29 | SECPK1/IntGroup.o main.o SECPK1/Random.o \ 30 | Timer.o SECPK1/Int.o SECPK1/IntMod.o \ 31 | SECPK1/Point.o SECPK1/SECP256K1.o \ 32 | Kangaroo.o HashTable.o Thread.o Check.o Backup.o \ 33 | Network.o Merge.o PartMerge.o) 34 | 35 | endif 36 | 37 | CXX = g++ 38 | CUDA = /usr/local/cuda 39 | CXXCUDA = /usr/bin/g++ 40 | NVCC = $(CUDA)/bin/nvcc 41 | 42 | all: driverquery bsgs 43 | 44 | ifdef gpu 45 | ifndef ccap 46 | driverquery: 47 | . ./detect_cuda.sh 48 | ccap=$(shell cat cuda_version.txt) 49 | else 50 | driverquery: 51 | @echo "Compiling against manually selected CUDA version ${ccap}" 52 | endif 53 | else 54 | driverquery: 55 | endif 56 | 57 | ifdef gpu 58 | 59 | ifdef debug 60 | CXXFLAGS = -DWITHGPU -m64 -mssse3 -Wno-unused-result -Wno-write-strings -g -I. -I$(CUDA)/include 61 | else 62 | CXXFLAGS = -DWITHGPU -m64 -mssse3 -Wno-unused-result -Wno-write-strings -O2 -I. -I$(CUDA)/include 63 | endif 64 | LFLAGS = -lpthread -L$(CUDA)/lib64 -lcudart 65 | 66 | else 67 | 68 | ifdef cpu 69 | CXXFLAGS = -m64 -march=native -mtune=native -mssse3 -Wno-unused-result -Wno-write-strings -pthread -ftree-vectorize -flto -O3 -funroll-loops -finline-functions -I. 70 | LFLAGS = -lpthread 71 | 72 | else 73 | 74 | ifdef debug 75 | CXXFLAGS = -m64 -mssse3 -Wno-unused-result -Wno-write-strings -g -I. -I$(CUDA)/include 76 | else 77 | CXXFLAGS = -m64 -mssse3 -Wno-unused-result -Wno-write-strings -O2 -I. -I$(CUDA)/include 78 | endif 79 | LFLAGS = -lpthread 80 | 81 | endif 82 | endif 83 | 84 | #-------------------------------------------------------------------- 85 | 86 | ifdef gpu 87 | ifdef debug 88 | $(OBJDIR)/GPU/GPUEngine.o: GPU/GPUEngine.cu 89 | $(NVCC) -G -maxrregcount=0 --ptxas-options=-v --compile --compiler-options -fPIC -ccbin $(CXXCUDA) -m64 -g -I$(CUDA)/include -gencode=arch=compute_$(ccap),code=sm_$(ccap) -o $(OBJDIR)/GPU/GPUEngine.o -c GPU/GPUEngine.cu 90 | else 91 | $(OBJDIR)/GPU/GPUEngine.o: GPU/GPUEngine.cu 92 | $(NVCC) -maxrregcount=0 --ptxas-options=-v --compile --compiler-options -fPIC -ccbin $(CXXCUDA) -m64 -O2 -I$(CUDA)/include -gencode=arch=compute_$(ccap),code=sm_$(ccap) -o $(OBJDIR)/GPU/GPUEngine.o -c GPU/GPUEngine.cu 93 | endif 94 | endif 95 | 96 | $(OBJDIR)/%.o : %.cpp 97 | $(CXX) $(CXXFLAGS) -o $@ -c $< 98 | 99 | bsgs: $(OBJET) 100 | @echo Making Kangaroo-256... 101 | $(CXX) $(OBJET) $(LFLAGS) -o kangaroo-256 102 | 103 | $(OBJET): | $(OBJDIR) $(OBJDIR)/SECPK1 $(OBJDIR)/GPU 104 | 105 | $(OBJDIR): 106 | mkdir -p $(OBJDIR) 107 | 108 | $(OBJDIR)/GPU: $(OBJDIR) 109 | cd $(OBJDIR) && mkdir -p GPU 110 | 111 | $(OBJDIR)/SECPK1: $(OBJDIR) 112 | cd $(OBJDIR) && mkdir -p SECPK1 113 | 114 | clean: 115 | @echo Cleaning... 116 | @rm -f kangaroo-256 117 | @rm -f obj/*.o 118 | @rm -f obj/GPU/*.o 119 | @rm -f obj/SECPK1/*.o 120 | @rm -f deviceQuery/*.o 121 | @rm -f cuda_version.txt 122 | @rm -f deviceQuery/cuda_build_log.txt 123 | -------------------------------------------------------------------------------- /Merge.cpp: -------------------------------------------------------------------------------- 1 | #include "Kangaroo.h" 2 | #include 3 | #include "SECPK1/IntGroup.h" 4 | #include "Timer.h" 5 | #include 6 | #define _USE_MATH_DEFINES 7 | #include 8 | #include 9 | #ifndef WIN64 10 | #include 11 | #include 12 | #endif 13 | 14 | using namespace std; 15 | 16 | bool Kangaroo::MergeWork(std::string& file1,std::string& file2,std::string& dest,bool printStat) { 17 | 18 | if(IsDir(file1) && IsDir(file2)) { 19 | return MergeWorkPartPart(file1,file2); 20 | } 21 | 22 | if(IsDir(file1)) { 23 | return MergeWorkPart(file1,file2,true); 24 | } 25 | 26 | if(dest.length()==0) { 27 | ::printf("MergeWork: destination argument missing\n"); 28 | return true; 29 | } 30 | 31 | double t0; 32 | double t1; 33 | uint32_t v1; 34 | uint32_t v2; 35 | 36 | t0 = Timer::get_tick(); 37 | 38 | // --------------------------------------------------- 39 | FILE* f1 = ReadHeader(file1,&v1,HEADW); 40 | if(f1 == NULL) 41 | return false; 42 | 43 | uint32_t dp1; 44 | Point k1; 45 | uint64_t count1; 46 | double time1; 47 | Int RS1; 48 | Int RE1; 49 | 50 | // Read global param 51 | ::fread(&dp1,sizeof(uint32_t),1,f1); 52 | ::fread(&RS1.bits64,32,1,f1); RS1.bits64[4] = 0; 53 | ::fread(&RE1.bits64,32,1,f1); RE1.bits64[4] = 0; 54 | ::fread(&k1.x.bits64,32,1,f1); k1.x.bits64[4] = 0; 55 | ::fread(&k1.y.bits64,32,1,f1); k1.y.bits64[4] = 0; 56 | ::fread(&count1,sizeof(uint64_t),1,f1); 57 | ::fread(&time1,sizeof(double),1,f1); 58 | 59 | k1.z.SetInt32(1); 60 | if(!secp->EC(k1)) { 61 | ::printf("MergeWork: key1 does not lie on elliptic curve\n"); 62 | fclose(f1); 63 | return true; 64 | } 65 | 66 | 67 | // --------------------------------------------------- 68 | 69 | FILE* f2 = ReadHeader(file2,&v2,HEADW); 70 | if(f2 == NULL) { 71 | fclose(f1); 72 | return true; 73 | } 74 | 75 | uint32_t dp2; 76 | Point k2; 77 | uint64_t count2; 78 | double time2; 79 | Int RS2; 80 | Int RE2; 81 | 82 | // Read global param 83 | ::fread(&dp2,sizeof(uint32_t),1,f2); 84 | ::fread(&RS2.bits64,32,1,f2); RS2.bits64[4] = 0; 85 | ::fread(&RE2.bits64,32,1,f2); RE2.bits64[4] = 0; 86 | ::fread(&k2.x.bits64,32,1,f2); k2.x.bits64[4] = 0; 87 | ::fread(&k2.y.bits64,32,1,f2); k2.y.bits64[4] = 0; 88 | ::fread(&count2,sizeof(uint64_t),1,f2); 89 | ::fread(&time2,sizeof(double),1,f2); 90 | 91 | if(v1 != v2) { 92 | ::printf("MergeWork: cannot merge workfile of different version\n"); 93 | fclose(f1); 94 | fclose(f2); 95 | return true; 96 | } 97 | 98 | k2.z.SetInt32(1); 99 | if(!secp->EC(k2)) { 100 | ::printf("MergeWork: key2 does not lie on elliptic curve\n"); 101 | fclose(f1); 102 | fclose(f2); 103 | return true; 104 | } 105 | 106 | if(!RS1.IsEqual(&RS2) || !RE1.IsEqual(&RE2)) { 107 | 108 | ::printf("MergeWork: File range differs\n"); 109 | ::printf("RS1: %s\n",RS1.GetBase16().c_str()); 110 | ::printf("RE1: %s\n",RE1.GetBase16().c_str()); 111 | ::printf("RS2: %s\n",RS2.GetBase16().c_str()); 112 | ::printf("RE2: %s\n",RE2.GetBase16().c_str()); 113 | fclose(f1); 114 | fclose(f2); 115 | return true; 116 | 117 | } 118 | 119 | if(!k1.equals(k2)) { 120 | 121 | ::printf("MergeWork: key differs, multiple keys not yet supported\n"); 122 | fclose(f1); 123 | fclose(f2); 124 | return true; 125 | 126 | } 127 | 128 | ::printf("File %s: [DP%d]\n",file1.c_str(),dp1); 129 | ::printf("File %s: [DP%d]\n",file2.c_str(),dp2); 130 | 131 | endOfSearch = false; 132 | 133 | // Set starting parameters 134 | keysToSearch.clear(); 135 | keysToSearch.push_back(k1); 136 | keyIdx = 0; 137 | collisionInSameHerd = 0; 138 | rangeStart.Set(&RS1); 139 | rangeEnd.Set(&RE1); 140 | InitRange(); 141 | InitSearchKey(); 142 | 143 | t0 = Timer::get_tick(); 144 | 145 | #ifndef WIN64 146 | setvbuf(stdout, NULL, _IONBF, 0); 147 | #endif 148 | 149 | ::printf("Merging"); 150 | 151 | // Open output file 152 | string tmpName = dest + ".tmp"; 153 | FILE* f = fopen(tmpName.c_str(),"wb"); 154 | if(f == NULL) { 155 | ::printf("\nMergeWork: Cannot open %s for writing\n",tmpName.c_str()); 156 | ::printf("%s\n",::strerror(errno)); 157 | fclose(f1); 158 | fclose(f2); 159 | return true; 160 | } 161 | dpSize = (dp1 < dp2) ? dp1 : dp2; 162 | if( !SaveHeader(tmpName,f,HEADW,count1 + count2,time1 + time2) ) { 163 | fclose(f1); 164 | fclose(f2); 165 | fclose(f); 166 | return true; 167 | } 168 | 169 | uint64_t nbDP = 0; 170 | uint32_t hDP; 171 | uint32_t hDuplicate; 172 | Int d1; 173 | uint32_t type1; 174 | Int d2; 175 | uint32_t type2; 176 | 177 | for(uint32_t h=0;h rhs.size; } 237 | 238 | void Kangaroo::MergeDir(std::string& dirName,std::string& dest) { 239 | 240 | vector listFiles; 241 | 242 | #ifdef WIN64 243 | WIN32_FIND_DATA ffd; 244 | HANDLE hFind; 245 | 246 | hFind = FindFirstFile((dirName.c_str()+string("\\*")).c_str(),&ffd); 247 | if( hFind==INVALID_HANDLE_VALUE ) { 248 | ::printf("FindFirstFile Error: %d\n",GetLastError()); 249 | return; 250 | } 251 | 252 | do { 253 | if((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==0) { 254 | uint32_t version; 255 | string fName = dirName.c_str() + string("\\") + string(ffd.cFileName); 256 | FILE *f = ReadHeader(fName,&version,HEADW); 257 | if(f) { 258 | File e; 259 | e.name = fName; 260 | _fseeki64(f,0,SEEK_END); 261 | e.size = (uint64_t)_ftelli64(f); 262 | listFiles.push_back(e); 263 | fclose(f); 264 | } 265 | } 266 | } while(FindNextFile(hFind,&ffd) != 0); 267 | FindClose(hFind); 268 | 269 | #else 270 | 271 | DIR *dir; 272 | struct dirent *ent; 273 | if ((dir = opendir(dirName.c_str())) != NULL) { 274 | while ((ent = readdir(dir)) != NULL) { 275 | if ( ent->d_type != 0x8) continue; 276 | uint32_t version; 277 | string fName = dirName + "/" + string(ent->d_name); 278 | FILE *f = ReadHeader(fName,&version,HEADW); 279 | if(f) { 280 | File e; 281 | e.name = fName; 282 | fseeko(f,0,SEEK_END); 283 | e.size = (uint64_t)ftello(f); 284 | listFiles.push_back(e); 285 | fclose(f); 286 | } 287 | 288 | } 289 | closedir(dir); 290 | } else { 291 | ::printf("opendir(%s) Error:\n",dirName.c_str()); 292 | perror(""); 293 | return; 294 | } 295 | 296 | #endif 297 | 298 | std::sort(listFiles.begin(),listFiles.end(),sortBySize); 299 | int lgth = (int)listFiles.size(); 300 | 301 | if(IsDir(dest)==1) { 302 | 303 | // Partitioned merge 304 | bool end = false; 305 | for(int i = 0; i < lgth && !end; i++) { 306 | ::printf("\n## File #%d/%d\n",i+1,lgth); 307 | end = MergeWorkPart(dest,listFiles[i].name,i == lgth - 1); 308 | } 309 | 310 | } else { 311 | 312 | // Standard merge 313 | if(listFiles.size() < 2) { 314 | ::printf("MergeDir: less than 2 work files in the directory\n"); 315 | return; 316 | } 317 | 318 | int i = 0; 319 | ::printf("\n## File #1/%d\n",lgth - 1); 320 | bool end = MergeWork(listFiles[0].name,listFiles[1].name,dest,lgth == 2); 321 | for(int i = 2; i < lgth && !end; i++) { 322 | ::printf("\n## File #%d/%d\n",i,lgth - 1); 323 | end = MergeWork(dest,listFiles[i].name,dest,i == lgth - 1); 324 | } 325 | 326 | } 327 | 328 | 329 | } 330 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pollard's kangaroo for SECPK1 2 | 3 | This 256bit version is based on: 4 | 5 | https://github.com/JeanLucPons/Kangaroo 125bit version 6 | 7 | With ideas from: 8 | 9 | https://github.com/ZenulAbidin/Kangaroo-256 (said to be buggy and not finished) 10 | 11 | https://github.com/Totulik/Kangaroo-254-bit 12 | 13 | https://github.com/AlberTajuelo/kangaroo 14 | 15 | A Pollard's kangaroo interval ECDLP solver for SECP256K1 (based on VanitySearch engine). 16 | 17 | # Feature 18 | 19 |
    20 |
  • Fixed size arithmetic.
  • 21 |
  • Fast Modular Inversion (Delayed Right Shift 62 bits).
  • 22 |
  • SecpK1 Fast modular multiplication (2 steps folding 512bits to 256bits reduction using 64 bits digits).
  • 23 |
  • Multi-GPU support.
  • 24 |
  • CUDA optimisation via inline PTX assembly.
  • 25 |
  • Full 256-bit interval search.
  • 26 |
27 | 28 | # Discussion Thread 29 | 30 | Discusion thread: https://bitcointalk.org/index.php?topic=5244940.0 31 | 32 | # Usage 33 | 34 | ``` 35 | Kangaroo v2.3 36 | Kangaroo [-v] [-t nbThread] [-d dpBit] [gpu] [-check] 37 | [-gpuId gpuId1[,gpuId2,...]] [-g g1x,g1y[,g2x,g2y,...]] 38 | inFile 39 | -v: Print version 40 | -gpu: Enable gpu calculation 41 | -gpuId gpuId1,gpuId2,...: List of GPU(s) to use, default is 0 42 | -g g1x,g1y,g2x,g2y,...: Specify GPU(s) kernel gridsize, default is 2*(MP),2*(Core/MP) 43 | -d: Specify number of leading zeros for the DP method (default is auto) 44 | -t nbThread: Secify number of thread 45 | -w workfile: Specify file to save work into (current processed key only) 46 | -i workfile: Specify file to load work from (current processed key only) 47 | -wi workInterval: Periodic interval (in seconds) for saving work 48 | -ws: Save kangaroos in the work file 49 | -wss: Save kangaroos via the server 50 | -wsplit: Split work file of server and reset hashtable 51 | -wm file1 file2 destfile: Merge work file 52 | -wmdir dir destfile: Merge directory of work files 53 | -wt timeout: Save work timeout in millisec (default is 3000ms) 54 | -winfo file1: Work file info file 55 | -wpartcreate name: Create empty partitioned work file (name is a directory) 56 | -wcheck worfile: Check workfile integrity 57 | -m maxStep: number of operations before give up the search (maxStep*expected operation) 58 | -s: Start in server mode 59 | -c server_ip: Start in client mode and connect to server server_ip 60 | -sp port: Server port, default is 17403 61 | -nt timeout: Network timeout in millisec (default is 3000ms) 62 | -o fileName: output result to fileName 63 | -l: List cuda enabled devices 64 | -check: Check GPU kernel vs CPU 65 | inFile: intput configuration file 66 | ``` 67 | 68 | Structure of the input file: 69 | * All values are in hex format 70 | * Public keys can be given either in compressed or uncompressed format 71 | 72 | ``` 73 | Start range 74 | End range 75 | Key #1 76 | ``` 77 | 78 | ex 79 | 80 | ``` 81 | 200000000000000000000000000000000 82 | 3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 83 | 03633CBE3EC02B9401C5EFFA144C5B4D22F87940259634858FC7E59B1C09937852 84 | ``` 85 | 86 | # Note on Time/Memory tradeoff of the DP method 87 | 88 | The distinguished point (DP) method is an efficient method for storing random walks and detect collision between them. Instead of storing all points of all kangagroo's random walks, we store only points that have an x value starting with dpBit zero bits. When 2 kangaroos collide, they will then follow the same path because their jumps are a function of their x values. The collision will be then detected when the 2 kangaroos reach a distinguished point.\ 89 | This has a drawback when you have a lot of kangaroos and looking for collision in a small range as the overhead is in the order of nbKangaroo.2dpBit until a collision is detected. If dpBit is too small a large number of point will enter in the central table, will decrease performance and quickly fill the RAM. 90 | **Powerfull GPUs with large number of cores won't be very efficient on small range, you can try to decrease the grid size in order to have less kangaroos but the GPU performance may not be optimal.** 91 | Yau can change manualy the DP mask size using the -d option, take in consideration that it will require more operations to complete. See table below: 92 | 93 | | nbKangaroo.2dpBit/sqrt(N) | DP Overhead | Avg | 94 | |--------------------------------------|:------------:|:---:| 95 | | 4.000 | cubicroot(1+4.000) = ~71.0% | 3.55 sqrt(N) | 96 | | 2.000 | cubicroot(1+2.000) = ~44.2% | 2.99 sqrt(N) | 97 | | 1.000 | cubicroot(1+1.000) = ~26.0% | 2.62 sqrt(N) | 98 | | 0.500 | cubicroot(1+0.500) = ~14.5% | 2.38 sqrt(N) | 99 | | 0.250 | cubicroot(1+0.250) = ~7.7% | 2.24 sqrt(N) | 100 | | 0.125 | cubicroot(1+0.125) = ~4.0% | 2.16 sqrt(N) | 101 | 102 | DP overhead according to the range size (N), DP mask size (dpBit) and number of kangaroos running in paralell (nbKangaroo). 103 | 104 | # Probability of success 105 | 106 | The picture below show the probability of success after a certain number of group operations. N is range size. 107 | This plot does not take into consideration the DP overhead. 108 | 109 | ![Probability of success](DOC/successprob.jpg) 110 | 111 | 112 | # How it works 113 | 114 | The program uses 2 herds of kangaroos, a tame herd and a wild herd. When 2 kangoroos (a wild one and a tame one) collide, the 115 | key can be solved. Due to the birthday paradox, a collision happens (in average) after 2.08*sqrt(k2-k1) [1] group operations, the 2 herds have the same size. To detect collision, the distinguished points method is used with a hashtable. 116 | 117 | Here is a brief description of the algorithm: 118 | 119 | We have to solve P = k.G, P is the public key, we know that k lies in the range [k1,k2], G is the SecpK1 generator point.\ 120 | Group operations are additions on the elliptic curve, scalar operations are done modulo the order of the curve. 121 | 122 | n = floor(log2(sqrt(k2-k1)))+1 123 | 124 | * Create a jump point table jP = [G,2G,4G,8G,...,2n-1.G] 125 | * Create a jump distance table jD = [1,2,4,8,....,2n-1] 126 | 127 | for all i in herdSize
128 |   tamei = rand(0..(k2-k1)) # Scalar operation
129 |   tamePosi = (k1+tamei).G # Group operation
130 |   wildi = rand(0..(k2-k1)) - (k2-k1)/2 # Scalar operation
131 |   wildPosi = P + wildi.G # Group operation
132 | 133 | found = false
134 | 135 | while not found
136 |   for all i in herdSize
137 |      tamePosi = tamePosi + jP[tamePosi.x % n] # Group operation
138 |      tamei += jD[tamePosi.x % n] # Scalar operation
139 |      wildPosi = wildPosi + jP[wildPosi.x % n] # Group operation
140 |      wildi += jD[wildPosi.x % n] # Scalar operation
141 |      if tamePosi is distinguished
142 |        add (TAME,tamePosi,tamei) to hashTable
143 |      if wildPosi is distinguished
144 |        add (WILD,wildPosi,wildi) to hashTable
145 |   found = is there a collision in hashTable between a tame and a wild kangaroo ?
146 |
147 | 148 | (Tame,Wild) = Collision
149 | k = k1 + Tame.dist - Wild.dist
150 | 151 | 152 | Here is an illustration of what's happening. When 2 paths collide they form a shape similar to the lambda letter. This is why this method is also called lambda method. 153 | 154 | ![Paths](DOC/paths.jpg) 155 | 156 | # Compilation 157 | 158 | Compilation Commands: 159 | ``` 160 | make gpu=1 Compile with GPU support. 161 | 162 | make cpu=1 Compile optimized for CPUs. 163 | 164 | make debug=1 Compile with debug symbols for debugging. 165 | ``` 166 | 167 | Main Target: Compiles the final executable kangaroo-256. 168 | 169 | Dependency Management: Ensures that necessary directories ($(OBJDIR), $(OBJDIR)/SECPK1, $(OBJDIR)/GPU) are created before compiling. 170 | 171 | Cleaning: Removes all object files and other generated files (cuda_version.txt, deviceQuery/cuda_build_log.txt) when make clean is invoked. 172 | 173 | This Makefile structure allows you to easily switch between different compilation configurations (amd, gpu, default) by setting appropriate flags when invoking make, or by modifying the Makefile directly. Adjust paths (CUDA, CXXCUDA), compiler flags (CXXFLAGS, LFLAGS), and dependencies (SRC, OBJET) as per your project's requirements. 174 | 175 | ## Windows 176 | 177 | Install CUDA SDK 10.2 and open VC_CUDA102\Kangaroo.sln in Visual C++ 2019.\ 178 | You may need to reset your *Windows SDK version* in project properties.\ 179 | In Build->Configuration Manager, select the *Release* configuration.\ 180 | Build and enjoy.\ 181 | \ 182 | Note: The current release has been compiled with Visual studio 2019 and CUDA SDK 10.2, if you have a different release of the CUDA SDK, you may need to update CUDA SDK paths in Kangaroo.vcxproj using a text editor. The current nvcc option are set up to architecture starting at 3.0 capability, for older hardware, add the desired compute capabilities to the list in GPUEngine.cu properties, CUDA C/C++, Device, Code Generation. 183 | 184 | Visual Sutido 2017 + Cuda 10 => Take project files in VC_CUDA10 (project files might be out of date)\ 185 | Visual Studio 2019 + Cuda10.2 => Take project files in VC_CUDA102\ 186 | 187 | ## Linux 188 | 189 | Install CUDA SDK.\ 190 | Depending on the CUDA SDK version and on your Linux distribution you may need to install an older g++ (just for the CUDA SDK).\ 191 | Edit the makefile and set up the good CUDA SDK path and appropriate compiler for nvcc. 192 | 193 | ``` 194 | CUDA = /usr/local/cuda-8.0 195 | CXXCUDA = /usr/bin/g++-4.8 196 | ``` 197 | 198 | You can enter a list of architecture (refer to nvcc documentation) if you have several GPU with different architecture. Compute capability 2.0 (Fermi) is deprecated for recent CUDA SDK. 199 | Kangaroo need to be compiled and linked with a recent gcc (>=7). The current release has been compiled with gcc 7.3.0.\ 200 | Go to the Kangaroo directory. ccap is the desired compute capability. 201 | 202 | ``` 203 | $ g++ -v 204 | gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04) 205 | $ make all (for build without CUDA support) 206 | or 207 | $ make gpu=1 ccap=20 all 208 | ``` 209 | 210 | Example with a 65bit key: 211 | ``` 212 | ./kangaroo-256 65.txt 213 | ``` 214 | 215 | ``` 216 | [+] Kangaroo v2.3 [256 range edition] 217 | [+] Start:10000000000000000 218 | [+] Stop :1FFFFFFFFFFFFFFFF 219 | [+] Keys :1 220 | [+] Number of CPU thread: 12 221 | [+] Range width: 2^64 222 | [+] Jump Avg distance: 2^31.99 223 | [+] Number of kangaroos: 2^13.58 224 | [+] Suggested DP: 15 225 | [+] Expected operations: 2^33.10 226 | [+] Expected RAM: 33.4MB 227 | [+] DP size: 15 [0x0007fff] 228 | [+] SolveKeyCPU Thread 06: 1024 kangaroos 229 | [+] SolveKeyCPU Thread 01: 1024 kangaroos 230 | [+] SolveKeyCPU Thread 04: 1024 kangaroos 231 | [+] SolveKeyCPU Thread 02: 1024 kangaroos 232 | [+] SolveKeyCPU Thread 00: 1024 kangaroos 233 | [+] SolveKeyCPU Thread 09: 1024 kangaroos 234 | [+] SolveKeyCPU Thread 10: 1024 kangaroos 235 | [+] SolveKeyCPU Thread 11: 1024 kangaroos 236 | [+] SolveKeyCPU Thread 03: 1024 kangaroos 237 | [+] SolveKeyCPU Thread 08: 1024 kangaroos 238 | [+] SolveKeyCPU Thread 07: 1024 kangaroos 239 | [+] SolveKeyCPU Thread 05: 1024 kangaroos 240 | [+] [55.52 MK/s][GPU 0.00 MK/s][Count 2^31.71][Dead 1][01:12 (Avg 02:45)][9.4/22.2MB] 241 | [+] Done: Total time 01:13 242 | 243 | ``` 244 | All the public address and privatekeys will be saved in the file KEYFOUNDKEYFOUND.txt of your current directory. 245 | 246 | # Articles 247 | 248 | - [1] Using Equivalence Classes to Accelerate Solvingthe Discrete Logarithm Problem in a Short Interval\ 249 | https://www.iacr.org/archive/pkc2010/60560372/60560372.pdf 250 | - [2] Kangaroo Methods for Solving theInterval Discrete Logarithm Problem\ 251 | https://arxiv.org/pdf/1501.07019.pdf 252 | - [3] Factoring and Discrete Logarithms using Pseudorandom Walks\ 253 | https://www.math.auckland.ac.nz/~sgal018/crypto-book/ch14.pdf 254 | - [4] Kangaroos, Monopoly and Discrete Logarithms\ 255 | https://web.northeastern.edu/seigen/11Magic/KruskalsCount/PollardKangarooMonopoly.pdf 256 | -------------------------------------------------------------------------------- /SECPK1/Int.h: -------------------------------------------------------------------------------- 1 | 2 | // Big integer class (Fixed size) 3 | 4 | #ifndef BIGINTH 5 | #define BIGINTH 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include "Random.h" 12 | 13 | // We need 1 extra block for Knuth div algorithm , Montgomery multiplication and 14 | // ModInv 15 | #define BISIZE 256 16 | 17 | #if BISIZE == 256 18 | #define NB64BLOCK 5 19 | #define NB32BLOCK 10 20 | #elif BISIZE == 512 21 | #define NB64BLOCK 9 22 | #define NB32BLOCK 18 23 | #else 24 | #error Unsuported size 25 | #endif 26 | 27 | class Int { 28 | public: 29 | Int(); 30 | Int(int64_t i64); 31 | Int(uint64_t u64); 32 | Int(Int *a); 33 | 34 | // Op 35 | void Add(uint64_t a); 36 | void Add(Int *a); 37 | void Add(Int *a, Int *b); 38 | void AddOne(); 39 | void Sub(uint64_t a); 40 | void Sub(Int *a); 41 | void Sub(Int *a, Int *b); 42 | void SubOne(); 43 | void Mult(Int *a); 44 | uint64_t Mult(uint64_t a); 45 | uint64_t IMult(int64_t a); 46 | uint64_t Mult(Int *a, uint64_t b); 47 | uint64_t IMult(Int *a, int64_t b); 48 | void Mult(Int *a, Int *b); 49 | void Div(Int *a, Int *mod = NULL); 50 | void MultModN(Int *a, Int *b, Int *n); 51 | void Neg(); 52 | void Abs(); 53 | void Copy(Int *a); 54 | 55 | // Right shift (signed) 56 | void ShiftR(uint32_t n); 57 | void ShiftR32Bit(); 58 | void ShiftR64Bit(); 59 | // Left shift 60 | void ShiftL(uint32_t n); 61 | void ShiftL32Bit(); 62 | void ShiftL64Bit(); 63 | // Bit swap 64 | void SwapBit(int bitNumber); 65 | 66 | // Comp 67 | bool IsGreater(Int *a); 68 | bool IsGreaterOrEqual(Int *a); 69 | bool IsLowerOrEqual(Int *a); 70 | bool IsLower(Int *a); 71 | bool IsEqual(Int *a); 72 | bool IsZero(); 73 | bool IsOne(); 74 | bool IsStrictPositive(); 75 | bool IsPositive(); 76 | bool IsNegative(); 77 | bool IsEven(); 78 | bool IsOdd(); 79 | bool IsProbablePrime(); 80 | 81 | double ToDouble(); 82 | 83 | // Modular arithmetic 84 | 85 | // Setup field 86 | // n is the field characteristic 87 | // R used in Montgomery mult (R = 2^size(n)) 88 | // R2 = R^2, R3 = R^3, R4 = R^4 89 | static void SetupField(Int *n, Int *R = NULL, Int *R2 = NULL, Int *R3 = NULL, 90 | Int *R4 = NULL); 91 | static Int *GetR(); // Return R 92 | static Int *GetR2(); // Return R2 93 | static Int *GetR3(); // Return R3 94 | static Int *GetR4(); // Return R4 95 | static Int *GetFieldCharacteristic(); // Return field characteristic 96 | 97 | void GCD(Int *a); // this <- GCD(this,a) 98 | void Mod(Int *n); // this <- this (mod n) 99 | void ModInv(); // this <- this^-1 (mod n) 100 | void MontgomeryMult(Int *a, Int *b); // this <- a*b*R^-1 (mod n) 101 | void MontgomeryMult(Int *a); // this <- this*a*R^-1 (mod n) 102 | void ModAdd(Int *a); // this <- this+a (mod n) [0 181 | void ModHelper(Func opFunc); 182 | template 183 | void ModSubHelper(Func opFunc); 184 | void MatrixVecMul(Int *u, Int *v, int64_t _11, int64_t _12, int64_t _21, 185 | int64_t _22, uint64_t *cu, uint64_t *cv); 186 | void MatrixVecMul(Int *u, Int *v, int64_t _11, int64_t _12, int64_t _21, 187 | int64_t _22); 188 | uint64_t AddCh(Int *a, uint64_t ca, Int *b, uint64_t cb); 189 | uint64_t AddCh(Int *a, uint64_t ca); 190 | uint64_t AddC(Int *a); 191 | void AddAndShift(Int *a, Int *b, uint64_t cH); 192 | void ShiftL64BitAndSub(Int *a, int n); 193 | uint64_t Mult(Int *a, uint32_t b); 194 | int GetLowestBit(); 195 | void CLEAR(); 196 | void CLEARFF(); 197 | void DivStep62(Int *u, Int *v, int64_t *eta, int *pos, int64_t *uu, 198 | int64_t *uv, int64_t *vu, int64_t *vv); 199 | }; 200 | 201 | // Inline routines 202 | 203 | #ifndef WIN64 204 | 205 | // Missing intrinsics 206 | static uint64_t inline _umul128(uint64_t a, uint64_t b, uint64_t *h) { 207 | uint64_t rhi; 208 | uint64_t rlo; 209 | __asm__("mulq %[b];" : "=d"(rhi), "=a"(rlo) : "1"(a), [ b ] "rm"(b)); 210 | *h = rhi; 211 | return rlo; 212 | } 213 | 214 | static int64_t inline _mul128(int64_t a, int64_t b, int64_t *h) { 215 | uint64_t rhi; 216 | uint64_t rlo; 217 | __asm__("imulq %[b];" : "=d"(rhi), "=a"(rlo) : "1"(a), [ b ] "rm"(b)); 218 | *h = rhi; 219 | return rlo; 220 | } 221 | 222 | static uint64_t inline _udiv128(uint64_t hi, uint64_t lo, uint64_t d, 223 | uint64_t *r) { 224 | uint64_t q; 225 | uint64_t _r; 226 | __asm__("divq %[d];" : "=d"(_r), "=a"(q) : "d"(hi), "a"(lo), [ d ] "rm"(d)); 227 | *r = _r; 228 | return q; 229 | } 230 | 231 | static uint64_t inline __rdtsc() { 232 | uint32_t h; 233 | uint32_t l; 234 | __asm__("rdtsc;" : "=d"(h), "=a"(l)); 235 | return (uint64_t)h << 32 | (uint64_t)l; 236 | } 237 | 238 | #define __shiftright128(a, b, n) ((a) >> (n)) | ((b) << (64 - (n))) 239 | #define __shiftleft128(a, b, n) ((b) << (n)) | ((a) >> (64 - (n))) 240 | 241 | #define _subborrow_u64(a, b, c, d) \ 242 | __builtin_ia32_sbb_u64(a, b, c, (long long unsigned int *)d); 243 | #define _addcarry_u64(a, b, c, d) \ 244 | __builtin_ia32_addcarryx_u64(a, b, c, (long long unsigned int *)d); 245 | #define _byteswap_uint64 __builtin_bswap64 246 | #define LZC(x) __builtin_clzll(x) 247 | #define TZC(x) __builtin_ctzll(x) 248 | 249 | #else 250 | 251 | #include 252 | #define TZC(x) _tzcnt_u64(x) 253 | #define LZC(x) _lzcnt_u64(x) 254 | 255 | #endif 256 | 257 | #define LoadI64(i, i64) \ 258 | i.bits64[0] = i64; \ 259 | i.bits64[1] = i64 >> 63; \ 260 | i.bits64[2] = i.bits64[1]; \ 261 | i.bits64[3] = i.bits64[1]; \ 262 | i.bits64[4] = i.bits64[1]; 263 | 264 | static void inline imm_mul(uint64_t *x, uint64_t y, uint64_t *dst, 265 | uint64_t *carryH) { 266 | unsigned char c = 0; 267 | uint64_t h, carry; 268 | dst[0] = _umul128(x[0], y, &h); 269 | carry = h; 270 | c = _addcarry_u64(c, _umul128(x[1], y, &h), carry, dst + 1); 271 | carry = h; 272 | c = _addcarry_u64(c, _umul128(x[2], y, &h), carry, dst + 2); 273 | carry = h; 274 | c = _addcarry_u64(c, _umul128(x[3], y, &h), carry, dst + 3); 275 | carry = h; 276 | c = _addcarry_u64(c, _umul128(x[4], y, &h), carry, dst + 4); 277 | carry = h; 278 | #if NB64BLOCK > 5 279 | c = _addcarry_u64(c, _umul128(x[5], y, &h), carry, dst + 5); 280 | carry = h; 281 | c = _addcarry_u64(c, _umul128(x[6], y, &h), carry, dst + 6); 282 | carry = h; 283 | c = _addcarry_u64(c, _umul128(x[7], y, &h), carry, dst + 7); 284 | carry = h; 285 | c = _addcarry_u64(c, _umul128(x[8], y, &h), carry, dst + 8); 286 | carry = h; 287 | #endif 288 | *carryH = carry; 289 | } 290 | 291 | static void inline imm_imul(uint64_t *x, uint64_t y, uint64_t *dst, 292 | uint64_t *carryH) { 293 | unsigned char c = 0; 294 | uint64_t h, carry; 295 | dst[0] = _umul128(x[0], y, &h); 296 | carry = h; 297 | c = _addcarry_u64(c, _umul128(x[1], y, &h), carry, dst + 1); 298 | carry = h; 299 | c = _addcarry_u64(c, _umul128(x[2], y, &h), carry, dst + 2); 300 | carry = h; 301 | c = _addcarry_u64(c, _umul128(x[3], y, &h), carry, dst + 3); 302 | carry = h; 303 | #if NB64BLOCK > 5 304 | c = _addcarry_u64(c, _umul128(x[4], y, &h), carry, dst + 4); 305 | carry = h; 306 | c = _addcarry_u64(c, _umul128(x[5], y, &h), carry, dst + 5); 307 | carry = h; 308 | c = _addcarry_u64(c, _umul128(x[6], y, &h), carry, dst + 6); 309 | carry = h; 310 | c = _addcarry_u64(c, _umul128(x[7], y, &h), carry, dst + 7); 311 | carry = h; 312 | #endif 313 | c = _addcarry_u64(c, _mul128(x[NB64BLOCK - 1], y, (int64_t *)&h), carry, 314 | dst + NB64BLOCK - 1); 315 | carry = h; 316 | *carryH = carry; 317 | } 318 | 319 | static void inline imm_umul(uint64_t *x, uint64_t y, uint64_t *dst) { 320 | // Assume that x[NB64BLOCK-1] is 0 321 | unsigned char c = 0; 322 | uint64_t h, carry; 323 | dst[0] = _umul128(x[0], y, &h); 324 | carry = h; 325 | c = _addcarry_u64(c, _umul128(x[1], y, &h), carry, dst + 1); 326 | carry = h; 327 | c = _addcarry_u64(c, _umul128(x[2], y, &h), carry, dst + 2); 328 | carry = h; 329 | c = _addcarry_u64(c, _umul128(x[3], y, &h), carry, dst + 3); 330 | carry = h; 331 | #if NB64BLOCK > 5 332 | c = _addcarry_u64(c, _umul128(x[4], y, &h), carry, dst + 4); 333 | carry = h; 334 | c = _addcarry_u64(c, _umul128(x[5], y, &h), carry, dst + 5); 335 | carry = h; 336 | c = _addcarry_u64(c, _umul128(x[6], y, &h), carry, dst + 6); 337 | carry = h; 338 | c = _addcarry_u64(c, _umul128(x[7], y, &h), carry, dst + 7); 339 | carry = h; 340 | #endif 341 | _addcarry_u64(c, 0ULL, carry, dst + (NB64BLOCK - 1)); 342 | } 343 | 344 | static void inline shiftR(unsigned char n, uint64_t *d) { 345 | d[0] = __shiftright128(d[0], d[1], n); 346 | d[1] = __shiftright128(d[1], d[2], n); 347 | d[2] = __shiftright128(d[2], d[3], n); 348 | d[3] = __shiftright128(d[3], d[4], n); 349 | #if NB64BLOCK > 5 350 | d[4] = __shiftright128(d[4], d[5], n); 351 | d[5] = __shiftright128(d[5], d[6], n); 352 | d[6] = __shiftright128(d[6], d[7], n); 353 | d[7] = __shiftright128(d[7], d[8], n); 354 | #endif 355 | d[NB64BLOCK - 1] = ((int64_t)d[NB64BLOCK - 1]) >> n; 356 | } 357 | 358 | static void inline shiftR(unsigned char n, uint64_t *d, uint64_t h) { 359 | d[0] = __shiftright128(d[0], d[1], n); 360 | d[1] = __shiftright128(d[1], d[2], n); 361 | d[2] = __shiftright128(d[2], d[3], n); 362 | d[3] = __shiftright128(d[3], d[4], n); 363 | #if NB64BLOCK > 5 364 | d[4] = __shiftright128(d[4], d[5], n); 365 | d[5] = __shiftright128(d[5], d[6], n); 366 | d[6] = __shiftright128(d[6], d[7], n); 367 | d[7] = __shiftright128(d[7], d[8], n); 368 | #endif 369 | 370 | d[NB64BLOCK - 1] = __shiftright128(d[NB64BLOCK - 1], h, n); 371 | } 372 | 373 | static void inline shiftL(unsigned char n, uint64_t *d) { 374 | #if NB64BLOCK > 5 375 | d[8] = __shiftleft128(d[7], d[8], n); 376 | d[7] = __shiftleft128(d[6], d[7], n); 377 | d[6] = __shiftleft128(d[5], d[6], n); 378 | d[5] = __shiftleft128(d[4], d[5], n); 379 | #endif 380 | d[4] = __shiftleft128(d[3], d[4], n); 381 | d[3] = __shiftleft128(d[2], d[3], n); 382 | d[2] = __shiftleft128(d[1], d[2], n); 383 | d[1] = __shiftleft128(d[0], d[1], n); 384 | d[0] = d[0] << n; 385 | } 386 | 387 | static inline int isStrictGreater128(uint64_t h1, uint64_t l1, uint64_t h2, 388 | uint64_t l2) { 389 | if (h1 > h2) return 1; 390 | if (h1 == h2) return l1 > l2; 391 | return 0; 392 | } 393 | 394 | #endif // BIGINTH 395 | -------------------------------------------------------------------------------- /SECPK1/IntGroup.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "IntGroup.h" 3 | 4 | using namespace std; 5 | 6 | IntGroup::IntGroup(int size) { 7 | this->size = size; 8 | subp = (Int *)malloc(size * sizeof(Int)); 9 | } 10 | 11 | IntGroup::~IntGroup() { 12 | free(subp); 13 | } 14 | 15 | void IntGroup::Set(Int *pts) { 16 | ints = pts; 17 | } 18 | 19 | // Compute modular inversion of the whole group 20 | void IntGroup::ModInv() { 21 | 22 | Int newValue; 23 | Int inverse; 24 | 25 | subp[0].Set(&ints[0]); 26 | for (int i = 1; i < size; i++) { 27 | subp[i].ModMulK1(&subp[i - 1], &ints[i]); 28 | } 29 | 30 | // Do the inversion 31 | inverse.Set(&subp[size - 1]); 32 | inverse.ModInv(); 33 | 34 | for (int i = size - 1; i > 0; i--) { 35 | newValue.ModMulK1(&subp[i - 1], &inverse); 36 | inverse.ModMulK1(&ints[i]); 37 | ints[i].Set(&newValue); 38 | } 39 | 40 | ints[0].Set(&inverse); 41 | 42 | } -------------------------------------------------------------------------------- /SECPK1/IntGroup.h: -------------------------------------------------------------------------------- 1 | #ifndef INTGROUPH 2 | #define INTGROUPH 3 | 4 | #include "Int.h" 5 | #include 6 | 7 | class IntGroup { 8 | 9 | public: 10 | 11 | IntGroup(int size); 12 | ~IntGroup(); 13 | void Set(Int *pts); 14 | void ModInv(); 15 | 16 | private: 17 | 18 | Int *ints; 19 | Int *subp; 20 | int size; 21 | 22 | }; 23 | 24 | #endif // INTGROUPCPUH 25 | -------------------------------------------------------------------------------- /SECPK1/Point.cpp: -------------------------------------------------------------------------------- 1 | #include "Point.h" 2 | 3 | Point::Point() { 4 | } 5 | 6 | Point::Point(const Point &p) { 7 | x.Set((Int *)&p.x); 8 | y.Set((Int *)&p.y); 9 | z.Set((Int *)&p.z); 10 | } 11 | 12 | Point::Point(Int *cx,Int *cy,Int *cz) { 13 | x.Set(cx); 14 | y.Set(cy); 15 | z.Set(cz); 16 | } 17 | 18 | Point::Point(Int *cx, Int *cz) { 19 | x.Set(cx); 20 | z.Set(cz); 21 | } 22 | 23 | void Point::Clear() { 24 | x.SetInt32(0); 25 | y.SetInt32(0); 26 | z.SetInt32(0); 27 | } 28 | 29 | void Point::Set(Int *cx, Int *cy,Int *cz) { 30 | x.Set(cx); 31 | y.Set(cy); 32 | z.Set(cz); 33 | } 34 | 35 | Point::~Point() { 36 | } 37 | 38 | void Point::Set(Point &p) { 39 | x.Set(&p.x); 40 | y.Set(&p.y); 41 | } 42 | 43 | bool Point::isZero() { 44 | return x.IsZero() && y.IsZero(); 45 | } 46 | 47 | void Point::Reduce() { 48 | 49 | Int i(&z); 50 | i.ModInv(); 51 | x.ModMul(&x,&i); 52 | y.ModMul(&y,&i); 53 | z.SetInt32(1); 54 | 55 | } 56 | 57 | bool Point::equals(Point &p) { 58 | return x.IsEqual(&p.x) && y.IsEqual(&p.y) && z.IsEqual(&p.z); 59 | } 60 | 61 | std::string Point::toString() { 62 | 63 | std::string ret; 64 | ret = "X=" + x.GetBase16() + "\n"; 65 | ret += "Y=" + y.GetBase16() + "\n"; 66 | ret += "Z=" + z.GetBase16() + "\n"; 67 | return ret; 68 | 69 | } 70 | -------------------------------------------------------------------------------- /SECPK1/Point.h: -------------------------------------------------------------------------------- 1 | #ifndef POINTH 2 | #define POINTH 3 | 4 | #include "Int.h" 5 | 6 | class Point { 7 | 8 | public: 9 | 10 | Point(); 11 | Point(Int *cx,Int *cy,Int *cz); 12 | Point(Int *cx, Int *cz); 13 | Point(const Point &p); 14 | ~Point(); 15 | bool isZero(); 16 | bool equals(Point &p); 17 | void Set(Point &p); 18 | void Set(Int *cx, Int *cy,Int *cz); 19 | void Clear(); 20 | void Reduce(); 21 | std::string toString(); 22 | 23 | Int x; 24 | Int y; 25 | Int z; 26 | 27 | }; 28 | 29 | #endif // POINTH 30 | -------------------------------------------------------------------------------- /SECPK1/Random.cpp: -------------------------------------------------------------------------------- 1 | #include "Random.h" 2 | 3 | #define RK_STATE_LEN 624 4 | 5 | /* State of the RNG */ 6 | typedef struct rk_state_ 7 | { 8 | unsigned long key[RK_STATE_LEN]; 9 | int pos; 10 | } rk_state; 11 | 12 | rk_state localState; 13 | 14 | /* Maximum generated random value */ 15 | #define RK_MAX 0xFFFFFFFFUL 16 | 17 | void rk_seed(unsigned long seed, rk_state *state) 18 | { 19 | int pos; 20 | seed &= 0xffffffffUL; 21 | 22 | /* Knuth's PRNG as used in the Mersenne Twister reference implementation */ 23 | for (pos=0; poskey[pos] = seed; 26 | seed = (1812433253UL * (seed ^ (seed >> 30)) + pos + 1) & 0xffffffffUL; 27 | } 28 | 29 | state->pos = RK_STATE_LEN; 30 | } 31 | 32 | /* Magic Mersenne Twister constants */ 33 | #define N 624 34 | #define M 397 35 | #define MATRIX_A 0x9908b0dfUL 36 | #define UPPER_MASK 0x80000000UL 37 | #define LOWER_MASK 0x7fffffffUL 38 | 39 | #ifdef WIN32 40 | // Disable "unary minus operator applied to unsigned type, result still unsigned" warning. 41 | #pragma warning(disable : 4146) 42 | #endif 43 | 44 | /* Slightly optimised reference implementation of the Mersenne Twister */ 45 | inline unsigned long rk_random(rk_state *state) 46 | { 47 | unsigned long y; 48 | 49 | if (state->pos == RK_STATE_LEN) 50 | { 51 | int i; 52 | 53 | for (i=0;ikey[i] & UPPER_MASK) | (state->key[i+1] & LOWER_MASK); 56 | state->key[i] = state->key[i+M] ^ (y>>1) ^ (-(y & 1) & MATRIX_A); 57 | } 58 | for (;ikey[i] & UPPER_MASK) | (state->key[i+1] & LOWER_MASK); 61 | state->key[i] = state->key[i+(M-N)] ^ (y>>1) ^ (-(y & 1) & MATRIX_A); 62 | } 63 | y = (state->key[N-1] & UPPER_MASK) | (state->key[0] & LOWER_MASK); 64 | state->key[N-1] = state->key[M-1] ^ (y>>1) ^ (-(y & 1) & MATRIX_A); 65 | 66 | state->pos = 0; 67 | } 68 | 69 | y = state->key[state->pos++]; 70 | 71 | /* Tempering */ 72 | y ^= (y >> 11); 73 | y ^= (y << 7) & 0x9d2c5680UL; 74 | y ^= (y << 15) & 0xefc60000UL; 75 | y ^= (y >> 18); 76 | 77 | return y; 78 | } 79 | 80 | inline double rk_double(rk_state *state) 81 | { 82 | /* shifts : 67108864 = 0x4000000, 9007199254740992 = 0x20000000000000 */ 83 | long a = rk_random(state) >> 5, b = rk_random(state) >> 6; 84 | return (a * 67108864.0 + b) / 9007199254740992.0; 85 | } 86 | 87 | // Initialise the random generator with the specified seed 88 | void rseed(unsigned long seed) { 89 | rk_seed(seed,&localState); 90 | //srand(seed); 91 | } 92 | 93 | unsigned long rndl() { 94 | return rk_random(&localState); 95 | } 96 | 97 | // Returns a uniform distributed double value in the interval ]0,1[ 98 | double rnd() { 99 | return rk_double(&localState); 100 | } 101 | -------------------------------------------------------------------------------- /SECPK1/Random.h: -------------------------------------------------------------------------------- 1 | #ifndef RANDOM_H 2 | #define RANDOM_H 3 | 4 | double rnd(); 5 | unsigned long rndl(); 6 | void rseed(unsigned long seed); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /SECPK1/SECP256K1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "IntGroup.h" 4 | #include "SECP256k1.h" 5 | 6 | Secp256K1::Secp256K1() {} 7 | 8 | void Secp256K1::Init() { 9 | // Prime for the finite field 10 | Int P; 11 | P.SetBase16( 12 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"); 13 | 14 | // Set up field 15 | Int::SetupField(&P); 16 | 17 | // Generator point and order 18 | G.x.SetBase16( 19 | "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"); 20 | G.y.SetBase16( 21 | "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"); 22 | G.z.SetInt32(1); 23 | order.SetBase16( 24 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"); 25 | 26 | Int::InitK1(&order); 27 | 28 | // Compute Generator table 29 | Point N(G); 30 | for (int i = 0; i < 32; i++) { 31 | GTable[i * 256] = N; 32 | N = DoubleDirect(N); 33 | for (int j = 1; j < 255; j++) { 34 | GTable[i * 256 + j] = N; 35 | N = AddDirect(N, GTable[i * 256]); 36 | } 37 | GTable[i * 256 + 255] = N; // Dummy point for check function 38 | } 39 | } 40 | 41 | Secp256K1::~Secp256K1() {} 42 | 43 | Point Secp256K1::ComputePublicKey(Int *privKey, bool reduce) { 44 | int i = 0; 45 | uint8_t b; 46 | Point Q; 47 | Q.Clear(); 48 | 49 | // Search first significant byte 50 | for (i = 0; i < 32; i++) { 51 | b = privKey->GetByte(i); 52 | if (b) break; 53 | } 54 | 55 | if (i < 32) { 56 | Q = GTable[256 * i + (b - 1)]; 57 | i++; 58 | } 59 | 60 | for (; i < 32; i++) { 61 | b = privKey->GetByte(i); 62 | if (b) Q = Add2(Q, GTable[256 * i + (b - 1)]); 63 | } 64 | 65 | if (reduce) Q.Reduce(); 66 | return Q; 67 | } 68 | 69 | std::vector Secp256K1::ComputePublicKeys(std::vector &privKeys) { 70 | std::vector pts; 71 | IntGroup grp((int)privKeys.size()); 72 | Int *inv = new Int[privKeys.size()]; 73 | pts.reserve(privKeys.size()); 74 | 75 | for (int i = 0; i < privKeys.size(); i++) { 76 | Point P = ComputePublicKey(&privKeys[i], false); 77 | inv[i].Set(&P.z); 78 | pts.push_back(P); 79 | } 80 | 81 | grp.Set(inv); 82 | grp.ModInv(); 83 | 84 | for (int i = 0; i < privKeys.size(); i++) { 85 | pts[i].x.ModMulK1(inv + i); 86 | pts[i].y.ModMulK1(inv + i); 87 | pts[i].z.SetInt32(1); 88 | } 89 | 90 | delete[] inv; 91 | return pts; 92 | } 93 | 94 | Point Secp256K1::NextKey(Point &key) { 95 | // Input key must be reduced and different from G 96 | // in order to use AddDirect 97 | return AddDirect(key, G); 98 | } 99 | 100 | uint8_t Secp256K1::GetByte(std::string &str, int idx) { 101 | char tmp[3]; 102 | int val; 103 | 104 | tmp[0] = str.data()[2 * idx]; 105 | tmp[1] = str.data()[2 * idx + 1]; 106 | tmp[2] = 0; 107 | 108 | if (sscanf(tmp, "%X", &val) != 1) { 109 | printf( 110 | "ParsePublicKeyHex: Error invalid public key specified (unexpected " 111 | "hexadecimal digit)\n"); 112 | exit(-1); 113 | } 114 | 115 | return (uint8_t)val; 116 | } 117 | 118 | bool Secp256K1::ParsePublicKeyHex(std::string str, Point &ret, 119 | bool &isCompressed) { 120 | ret.Clear(); 121 | 122 | if (str.length() < 2) { 123 | printf( 124 | "ParsePublicKeyHex: Error invalid public key specified (66 or 130 " 125 | "character length)\n"); 126 | return false; 127 | } 128 | 129 | uint8_t type = GetByte(str, 0); 130 | 131 | switch (type) { 132 | case 0x02: 133 | if (str.length() != 66) { 134 | printf( 135 | "ParsePublicKeyHex: Error invalid public key specified (66 " 136 | "character length)\n"); 137 | return false; 138 | } 139 | for (int i = 0; i < 32; i++) ret.x.SetByte(31 - i, GetByte(str, i + 1)); 140 | ret.y = GetY(ret.x, true); 141 | isCompressed = true; 142 | break; 143 | 144 | case 0x03: 145 | if (str.length() != 66) { 146 | printf( 147 | "ParsePublicKeyHex: Error invalid public key specified (66 " 148 | "character length)\n"); 149 | return false; 150 | } 151 | for (int i = 0; i < 32; i++) ret.x.SetByte(31 - i, GetByte(str, i + 1)); 152 | ret.y = GetY(ret.x, false); 153 | isCompressed = true; 154 | break; 155 | 156 | case 0x04: 157 | if (str.length() != 130) { 158 | printf( 159 | "ParsePublicKeyHex: Error invalid public key specified (130 " 160 | "character length)\n"); 161 | exit(-1); 162 | } 163 | for (int i = 0; i < 32; i++) ret.x.SetByte(31 - i, GetByte(str, i + 1)); 164 | for (int i = 0; i < 32; i++) ret.y.SetByte(31 - i, GetByte(str, i + 33)); 165 | isCompressed = false; 166 | break; 167 | 168 | default: 169 | printf( 170 | "ParsePublicKeyHex: Error invalid public key specified (Unexpected " 171 | "prefix (only 02,03 or 04 allowed)\n"); 172 | return false; 173 | } 174 | 175 | ret.z.SetInt32(1); 176 | 177 | if (!EC(ret)) { 178 | printf( 179 | "ParsePublicKeyHex: Error invalid public key specified (Not lie on " 180 | "elliptic curve)\n"); 181 | return false; 182 | } 183 | 184 | return true; 185 | } 186 | 187 | std::string Secp256K1::GetPublicKeyHex(bool compressed, Point &pubKey) { 188 | unsigned char publicKeyBytes[128]; 189 | char tmp[3]; 190 | std::string ret; 191 | 192 | if (!compressed) { 193 | // Full public key 194 | publicKeyBytes[0] = 0x4; 195 | pubKey.x.Get32Bytes(publicKeyBytes + 1); 196 | pubKey.y.Get32Bytes(publicKeyBytes + 33); 197 | 198 | for (int i = 0; i < 65; i++) { 199 | sprintf(tmp, "%02X", (int)publicKeyBytes[i]); 200 | ret.append(tmp); 201 | } 202 | 203 | } else { 204 | // Compressed public key 205 | publicKeyBytes[0] = pubKey.y.IsEven() ? 0x2 : 0x3; 206 | pubKey.x.Get32Bytes(publicKeyBytes + 1); 207 | 208 | for (int i = 0; i < 33; i++) { 209 | sprintf(tmp, "%02X", (int)publicKeyBytes[i]); 210 | ret.append(tmp); 211 | } 212 | } 213 | 214 | return ret; 215 | } 216 | 217 | Point Secp256K1::AddDirect(Point &p1, Point &p2) { 218 | Int _s; 219 | Int _p; 220 | Int dy; 221 | Int dx; 222 | Point r; 223 | r.z.SetInt32(1); 224 | 225 | dy.ModSub(&p2.y, &p1.y); 226 | dx.ModSub(&p2.x, &p1.x); 227 | dx.ModInv(); 228 | _s.ModMulK1(&dy, &dx); // s = (p2.y-p1.y)*inverse(p2.x-p1.x); 229 | 230 | _p.ModSquareK1(&_s); // _p = pow2(s) 231 | 232 | r.x.ModSub(&_p, &p1.x); 233 | r.x.ModSub(&p2.x); // rx = pow2(s) - p1.x - p2.x; 234 | 235 | r.y.ModSub(&p2.x, &r.x); 236 | r.y.ModMulK1(&_s); 237 | r.y.ModSub(&p2.y); // ry = - p2.y - s*(ret.x-p2.x); 238 | 239 | return r; 240 | } 241 | 242 | std::vector Secp256K1::AddDirect(std::vector &p1, 243 | std::vector &p2) { 244 | if (p1.size() != p2.size()) { 245 | // Fatal error 246 | ::printf("Secp256K1::AddDirect: vectors have not the same size\n"); 247 | exit(-1); 248 | } 249 | 250 | // Accept p1=0 251 | 252 | int size = (int)p1.size(); 253 | 254 | std::vector pts; 255 | IntGroup grp(size); 256 | Int *dx = new Int[size]; 257 | pts.reserve(size); 258 | 259 | Int _s; 260 | Int _p; 261 | Int dy; 262 | Point r; 263 | 264 | // Compute DX 265 | for (int i = 0; i < size; i++) { 266 | dx[i].ModSub(&p2[i].x, &p1[i].x); 267 | } 268 | grp.Set(dx); 269 | grp.ModInv(); 270 | 271 | for (int i = 0; i < size; i++) { 272 | if (p1[i].x.IsZero()) { 273 | pts.push_back(p2[i]); 274 | 275 | } else { 276 | dy.ModSub(&p2[i].y, &p1[i].y); 277 | _s.ModMulK1(&dy, &dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x); 278 | 279 | _p.ModSquareK1(&_s); // _p = pow2(s) 280 | 281 | r.x.ModSub(&_p, &p1[i].x); 282 | r.x.ModSub(&p2[i].x); // rx = pow2(s) - p1.x - p2.x; 283 | 284 | r.y.ModSub(&p2[i].x, &r.x); 285 | r.y.ModMulK1(&_s); 286 | r.y.ModSub(&p2[i].y); // ry = - p2.y - s*(ret.x-p2.x); 287 | 288 | pts.push_back(r); 289 | } 290 | } 291 | 292 | delete[] dx; 293 | return pts; 294 | } 295 | 296 | Point Secp256K1::Add2(Point &p1, Point &p2) { 297 | // P2.z = 1 298 | 299 | Int u; 300 | Int v; 301 | Int u1; 302 | Int v1; 303 | Int vs2; 304 | Int vs3; 305 | Int us2; 306 | Int a; 307 | Int us2w; 308 | Int vs2v2; 309 | Int vs3u2; 310 | Int _2vs2v2; 311 | Point r; 312 | 313 | u1.ModMulK1(&p2.y, &p1.z); 314 | v1.ModMulK1(&p2.x, &p1.z); 315 | u.ModSub(&u1, &p1.y); 316 | v.ModSub(&v1, &p1.x); 317 | us2.ModSquareK1(&u); 318 | vs2.ModSquareK1(&v); 319 | vs3.ModMulK1(&vs2, &v); 320 | us2w.ModMulK1(&us2, &p1.z); 321 | vs2v2.ModMulK1(&vs2, &p1.x); 322 | _2vs2v2.ModAdd(&vs2v2, &vs2v2); 323 | a.ModSub(&us2w, &vs3); 324 | a.ModSub(&_2vs2v2); 325 | 326 | r.x.ModMulK1(&v, &a); 327 | 328 | vs3u2.ModMulK1(&vs3, &p1.y); 329 | r.y.ModSub(&vs2v2, &a); 330 | r.y.ModMulK1(&r.y, &u); 331 | r.y.ModSub(&vs3u2); 332 | 333 | r.z.ModMulK1(&vs3, &p1.z); 334 | 335 | return r; 336 | } 337 | 338 | Point Secp256K1::Add(Point &p1, Point &p2) { 339 | Int u; 340 | Int v; 341 | Int u1; 342 | Int u2; 343 | Int v1; 344 | Int v2; 345 | Int vs2; 346 | Int vs3; 347 | Int us2; 348 | Int w; 349 | Int a; 350 | Int us2w; 351 | Int vs2v2; 352 | Int vs3u2; 353 | Int _2vs2v2; 354 | Int x3; 355 | Int vs3y1; 356 | Point r; 357 | 358 | /* 359 | U1 = Y2 * Z1 360 | U2 = Y1 * Z2 361 | V1 = X2 * Z1 362 | V2 = X1 * Z2 363 | if (V1 == V2) 364 | if (U1 != U2) 365 | return POINT_AT_INFINITY 366 | else 367 | return POINT_DOUBLE(X1, Y1, Z1) 368 | U = U1 - U2 369 | V = V1 - V2 370 | W = Z1 * Z2 371 | A = U ^ 2 * W - V ^ 3 - 2 * V ^ 2 * V2 372 | X3 = V * A 373 | Y3 = U * (V ^ 2 * V2 - A) - V ^ 3 * U2 374 | Z3 = V ^ 3 * W 375 | return (X3, Y3, Z3) 376 | */ 377 | 378 | u1.ModMulK1(&p2.y, &p1.z); 379 | u2.ModMulK1(&p1.y, &p2.z); 380 | v1.ModMulK1(&p2.x, &p1.z); 381 | v2.ModMulK1(&p1.x, &p2.z); 382 | u.ModSub(&u1, &u2); 383 | v.ModSub(&v1, &v2); 384 | w.ModMulK1(&p1.z, &p2.z); 385 | us2.ModSquareK1(&u); 386 | vs2.ModSquareK1(&v); 387 | vs3.ModMulK1(&vs2, &v); 388 | us2w.ModMulK1(&us2, &w); 389 | vs2v2.ModMulK1(&vs2, &v2); 390 | _2vs2v2.ModAdd(&vs2v2, &vs2v2); 391 | a.ModSub(&us2w, &vs3); 392 | a.ModSub(&_2vs2v2); 393 | 394 | r.x.ModMulK1(&v, &a); 395 | 396 | vs3u2.ModMulK1(&vs3, &u2); 397 | r.y.ModSub(&vs2v2, &a); 398 | r.y.ModMulK1(&r.y, &u); 399 | r.y.ModSub(&vs3u2); 400 | 401 | r.z.ModMulK1(&vs3, &w); 402 | 403 | return r; 404 | } 405 | 406 | Point Secp256K1::DoubleDirect(Point &p) { 407 | Int _s; 408 | Int _p; 409 | Int a; 410 | Point r; 411 | r.z.SetInt32(1); 412 | 413 | _s.ModMulK1(&p.x, &p.x); 414 | _p.ModAdd(&_s, &_s); 415 | _p.ModAdd(&_s); 416 | 417 | a.ModAdd(&p.y, &p.y); 418 | a.ModInv(); 419 | _s.ModMulK1(&_p, &a); // s = (3*pow2(p.x))*inverse(2*p.y); 420 | 421 | _p.ModMulK1(&_s, &_s); 422 | a.ModAdd(&p.x, &p.x); 423 | a.ModNeg(); 424 | r.x.ModAdd(&a, &_p); // rx = pow2(s) + neg(2*p.x); 425 | 426 | a.ModSub(&r.x, &p.x); 427 | 428 | _p.ModMulK1(&a, &_s); 429 | r.y.ModAdd(&_p, &p.y); 430 | r.y.ModNeg(); // ry = neg(p.y + s*(ret.x+neg(p.x))); 431 | 432 | return r; 433 | } 434 | 435 | Point Secp256K1::Double(Point &p) { 436 | /* 437 | if (Y == 0) 438 | return POINT_AT_INFINITY 439 | W = a * Z ^ 2 + 3 * X ^ 2 440 | S = Y * Z 441 | B = X * Y*S 442 | H = W ^ 2 - 8 * B 443 | X' = 2*H*S 444 | Y' = W*(4*B - H) - 8*Y^2*S^2 445 | Z' = 8*S^3 446 | return (X', Y', Z') 447 | */ 448 | 449 | Int z2; 450 | Int x2; 451 | Int _3x2; 452 | Int w; 453 | Int s; 454 | Int s2; 455 | Int b; 456 | Int _8b; 457 | Int _8y2s2; 458 | Int y2; 459 | Int h; 460 | Point r; 461 | 462 | z2.ModSquareK1(&p.z); 463 | z2.SetInt32(0); // a=0 464 | x2.ModSquareK1(&p.x); 465 | _3x2.ModAdd(&x2, &x2); 466 | _3x2.ModAdd(&x2); 467 | w.ModAdd(&z2, &_3x2); 468 | s.ModMulK1(&p.y, &p.z); 469 | b.ModMulK1(&p.y, &s); 470 | b.ModMulK1(&p.x); 471 | h.ModSquareK1(&w); 472 | _8b.ModAdd(&b, &b); 473 | _8b.ModDouble(); 474 | _8b.ModDouble(); 475 | h.ModSub(&_8b); 476 | 477 | r.x.ModMulK1(&h, &s); 478 | r.x.ModAdd(&r.x); 479 | 480 | s2.ModSquareK1(&s); 481 | y2.ModSquareK1(&p.y); 482 | _8y2s2.ModMulK1(&y2, &s2); 483 | _8y2s2.ModDouble(); 484 | _8y2s2.ModDouble(); 485 | _8y2s2.ModDouble(); 486 | 487 | r.y.ModAdd(&b, &b); 488 | r.y.ModAdd(&r.y, &r.y); 489 | r.y.ModSub(&h); 490 | r.y.ModMulK1(&w); 491 | r.y.ModSub(&_8y2s2); 492 | 493 | r.z.ModMulK1(&s2, &s); 494 | r.z.ModDouble(); 495 | r.z.ModDouble(); 496 | r.z.ModDouble(); 497 | 498 | return r; 499 | } 500 | 501 | Int Secp256K1::GetY(Int x, bool isEven) { 502 | Int _s; 503 | Int _p; 504 | 505 | _s.ModSquareK1(&x); 506 | _p.ModMulK1(&_s, &x); 507 | _p.ModAdd(7); 508 | _p.ModSqrt(); 509 | 510 | if (!_p.IsEven() && isEven) { 511 | _p.ModNeg(); 512 | } else if (_p.IsEven() && !isEven) { 513 | _p.ModNeg(); 514 | } 515 | 516 | return _p; 517 | } 518 | 519 | bool Secp256K1::EC(Point &p) { 520 | Int _s; 521 | Int _p; 522 | 523 | _s.ModSquareK1(&p.x); 524 | _p.ModMulK1(&_s, &p.x); 525 | _p.ModAdd(7); 526 | _s.ModMulK1(&p.y, &p.y); 527 | _s.ModSub(&_p); 528 | 529 | return _s.IsZero(); // ( ((pow2(y) - (pow3(x) + 7)) % P) == 0 ); 530 | } 531 | -------------------------------------------------------------------------------- /SECPK1/SECP256k1.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1H 2 | #define SECP256K1H 3 | 4 | #include "Point.h" 5 | #include 6 | #include 7 | 8 | class Secp256K1 { 9 | 10 | public: 11 | 12 | Secp256K1(); 13 | ~Secp256K1(); 14 | void Init(); 15 | Point ComputePublicKey(Int *privKey,bool reduce=true); 16 | std::vector ComputePublicKeys(std::vector &privKeys); 17 | Point NextKey(Point &key); 18 | bool EC(Point &p); 19 | 20 | std::string GetPublicKeyHex(bool compressed, Point &p); 21 | bool ParsePublicKeyHex(std::string str,Point &p,bool &isCompressed); 22 | 23 | Point Add(Point &p1, Point &p2); 24 | Point Add2(Point &p1, Point &p2); 25 | Point AddDirect(Point &p1, Point &p2); 26 | Point Double(Point &p); 27 | Point DoubleDirect(Point &p); 28 | 29 | std::vector AddDirect(std::vector &p1,std::vector &p2); 30 | 31 | Point G; // Generator 32 | Int order; // Curve order 33 | 34 | private: 35 | 36 | uint8_t GetByte(std::string &str,int idx); 37 | 38 | Int GetY(Int x, bool isEven); 39 | Point GTable[256*32]; // Generator table 40 | 41 | }; 42 | 43 | #endif // SECP256K1H 44 | -------------------------------------------------------------------------------- /Thread.cpp: -------------------------------------------------------------------------------- 1 | #include "Kangaroo.h" 2 | #include "Timer.h" 3 | #include 4 | #define _USE_MATH_DEFINES 5 | #include 6 | #include 7 | #ifndef WIN64 8 | #include 9 | #endif 10 | 11 | using namespace std; 12 | 13 | // ---------------------------------------------------------------------------- 14 | 15 | #ifdef WIN64 16 | 17 | THREAD_HANDLE Kangaroo::LaunchThread(LPTHREAD_START_ROUTINE func, TH_PARAM *p) { 18 | p->obj = this; 19 | return CreateThread(NULL, 0, func, (void*)(p), 0, NULL); 20 | } 21 | void Kangaroo::JoinThreads(THREAD_HANDLE *handles,int nbThread) { 22 | WaitForMultipleObjects(nbThread, handles, TRUE, INFINITE); 23 | } 24 | void Kangaroo::FreeHandles(THREAD_HANDLE *handles, int nbThread) { 25 | for (int i = 0; i < nbThread; i++) 26 | CloseHandle(handles[i]); 27 | } 28 | #else 29 | 30 | THREAD_HANDLE Kangaroo::LaunchThread(void *(*func) (void *), TH_PARAM *p) { 31 | THREAD_HANDLE h; 32 | p->obj = this; 33 | pthread_create(&h, NULL, func, (void*)(p)); 34 | return h; 35 | } 36 | void Kangaroo::JoinThreads(THREAD_HANDLE *handles, int nbThread) { 37 | for (int i = 0; i < nbThread; i++) 38 | pthread_join(handles[i], NULL); 39 | } 40 | void Kangaroo::FreeHandles(THREAD_HANDLE *handles, int nbThread) { 41 | } 42 | #endif 43 | 44 | // ---------------------------------------------------------------------------- 45 | 46 | bool Kangaroo::isAlive(TH_PARAM *p) { 47 | 48 | bool isAlive = false; 49 | int total = nbCPUThread + nbGPUThread; 50 | for(int i=0;i= 1) { 113 | 114 | double nbYear = nbDay / 365.0; 115 | if (nbYear > 1) { 116 | if (nbYear < 5) 117 | sprintf(tmp, "%.1fy", nbYear); 118 | else 119 | sprintf(tmp, "%gy", nbYear); 120 | } else { 121 | sprintf(tmp, "%.1fd", nbDay); 122 | } 123 | 124 | } else { 125 | 126 | int iTime = (int)dTime; 127 | int nbHour = (int)((iTime % 86400) / 3600); 128 | int nbMin = (int)(((iTime % 86400) % 3600) / 60); 129 | int nbSec = (int)(iTime % 60); 130 | 131 | if (nbHour == 0) { 132 | if (nbMin == 0) { 133 | sprintf(tmp, "%02ds", nbSec); 134 | } else { 135 | sprintf(tmp, "%02d:%02d", nbMin, nbSec); 136 | } 137 | } else { 138 | sprintf(tmp, "%02d:%02d:%02d", nbHour, nbMin, nbSec); 139 | } 140 | 141 | } 142 | 143 | return string(tmp); 144 | 145 | } 146 | 147 | // Wait for end of server and dispay stats 148 | void Kangaroo::ProcessServer() { 149 | 150 | double t0; 151 | double t1; 152 | t0 = Timer::get_tick(); 153 | startTime = t0; 154 | double lastSave = 0; 155 | 156 | // Acquire mutex ownership 157 | #ifndef WIN64 158 | pthread_mutex_init(&ghMutex, NULL); 159 | setvbuf(stdout, NULL, _IONBF, 0); 160 | #else 161 | ghMutex = CreateMutex(NULL,FALSE,NULL); 162 | #endif 163 | 164 | while(!endOfSearch) { 165 | 166 | t0 = Timer::get_tick(); 167 | 168 | LOCK(ghMutex); 169 | // Get back all dps 170 | localCache.clear(); 171 | for(int i=0;i<(int)recvDP.size();i++) 172 | localCache.push_back(recvDP[i]); 173 | recvDP.clear(); 174 | UNLOCK(ghMutex); 175 | 176 | // Add to hashTable 177 | for(int i = 0; i<(int)localCache.size() && !endOfSearch; i++) { 178 | DP_CACHE dp = localCache[i]; 179 | for(int j = 0; j<(int)dp.nbDP && !endOfSearch; j++) { 180 | if(!AddToTable(&dp.dp[j].x,&dp.dp[j].d,dp.dp[j].kIdx % 2)) { 181 | // Collision inside the same herd 182 | collisionInSameHerd++; 183 | } 184 | } 185 | free(dp.dp); 186 | } 187 | 188 | t1 = Timer::get_tick(); 189 | 190 | double toSleep = SEND_PERIOD - (t1-t0); 191 | if(toSleep<0) toSleep = 0.0; 192 | Timer::SleepMillis((uint32_t)(toSleep*1000.0)); 193 | 194 | t1 = Timer::get_tick(); 195 | 196 | if(!endOfSearch) 197 | printf("[+] [Client %d][Kang 2^%.2f][DP Count 2^%.2f/2^%.2f][Dead %.0f][%s][%s]\r", 198 | connectedClient, 199 | log2((double)totalRW), 200 | log2((double)hashTable.GetNbItem()), 201 | log2(expectedNbOp / pow(2.0,dpSize)), 202 | (double)collisionInSameHerd, 203 | GetTimeStr(t1 - startTime).c_str(), 204 | hashTable.GetSizeInfo().c_str() 205 | ); 206 | 207 | if(workFile.length() > 0 && !endOfSearch) { 208 | if((t1 - lastSave) > saveWorkPeriod) { 209 | SaveServerWork(); 210 | lastSave = t1; 211 | } 212 | } 213 | 214 | } 215 | 216 | } 217 | 218 | // Wait for end of threads and display stats 219 | void Kangaroo::Process(TH_PARAM *params,std::string unit) { 220 | 221 | double t0; 222 | double t1; 223 | 224 | uint64_t count; 225 | uint64_t lastCount = 0; 226 | uint64_t gpuCount = 0; 227 | uint64_t lastGPUCount = 0; 228 | double avgKeyRate = 0.0; 229 | double avgGpuKeyRate = 0.0; 230 | double lastSave = 0; 231 | 232 | #ifndef WIN64 233 | setvbuf(stdout, NULL, _IONBF, 0); 234 | #endif 235 | 236 | // Key rate smoothing filter 237 | #define FILTER_SIZE 8 238 | double lastkeyRate[FILTER_SIZE]; 239 | double lastGpukeyRate[FILTER_SIZE]; 240 | uint32_t filterPos = 0; 241 | 242 | double keyRate = 0.0; 243 | double gpuKeyRate = 0.0; 244 | 245 | memset(lastkeyRate,0,sizeof(lastkeyRate)); 246 | memset(lastGpukeyRate,0,sizeof(lastkeyRate)); 247 | 248 | // Wait that all threads have started 249 | while(!hasStarted(params)) 250 | Timer::SleepMillis(5); 251 | 252 | t0 = Timer::get_tick(); 253 | startTime = t0; 254 | lastGPUCount = getGPUCount(); 255 | lastCount = getCPUCount() + gpuCount; 256 | 257 | while(isAlive(params)) { 258 | 259 | int delay = 2000; 260 | while(isAlive(params) && delay > 0) { 261 | Timer::SleepMillis(50); 262 | delay -= 50; 263 | } 264 | 265 | gpuCount = getGPUCount(); 266 | count = getCPUCount() + gpuCount; 267 | 268 | t1 = Timer::get_tick(); 269 | keyRate = (double)(count - lastCount) / (t1 - t0); 270 | gpuKeyRate = (double)(gpuCount - lastGPUCount) / (t1 - t0); 271 | lastkeyRate[filterPos%FILTER_SIZE] = keyRate; 272 | lastGpukeyRate[filterPos%FILTER_SIZE] = gpuKeyRate; 273 | filterPos++; 274 | 275 | // KeyRate smoothing 276 | uint32_t nbSample; 277 | for(nbSample = 0; (nbSample < FILTER_SIZE) && (nbSample < filterPos); nbSample++) { 278 | avgKeyRate += lastkeyRate[nbSample]; 279 | avgGpuKeyRate += lastGpukeyRate[nbSample]; 280 | } 281 | avgKeyRate /= (double)(nbSample); 282 | avgGpuKeyRate /= (double)(nbSample); 283 | double expectedTime = expectedNbOp / avgKeyRate; 284 | 285 | // Display stats 286 | if(isAlive(params) && !endOfSearch) { 287 | if(clientMode) { 288 | printf("[+] [%.2f %s][GPU %.2f %s][Count 2^%.2f][%s][Server %6s] \r", 289 | avgKeyRate / 1000000.0,unit.c_str(), 290 | avgGpuKeyRate / 1000000.0,unit.c_str(), 291 | log2((double)count + offsetCount), 292 | GetTimeStr(t1 - startTime + offsetTime).c_str(), 293 | serverStatus.c_str() 294 | ); 295 | } else { 296 | printf("[+] [%.2f %s][GPU %.2f %s][Count 2^%.2f][Dead %.0f][%s (Avg %s)][%s] \r", 297 | avgKeyRate / 1000000.0,unit.c_str(), 298 | avgGpuKeyRate / 1000000.0,unit.c_str(), 299 | log2((double)count + offsetCount), 300 | (double)collisionInSameHerd, 301 | GetTimeStr(t1 - startTime + offsetTime).c_str(),GetTimeStr(expectedTime).c_str(), 302 | hashTable.GetSizeInfo().c_str() 303 | ); 304 | } 305 | 306 | } 307 | 308 | // Save request 309 | if(workFile.length() > 0 && !endOfSearch) { 310 | if((t1 - lastSave) > saveWorkPeriod) { 311 | SaveWork(count + offsetCount,t1 - startTime + offsetTime,params,nbCPUThread + nbGPUThread); 312 | lastSave = t1; 313 | } 314 | } 315 | 316 | // Abort 317 | if(!clientMode && maxStep>0.0) { 318 | double max = expectedNbOp * maxStep; 319 | if( (double)count > max ) { 320 | ::printf("\nKey#%2d [XX]Pub: 0x%s \n",keyIdx,secp->GetPublicKeyHex(true,keysToSearch[keyIdx]).c_str()); 321 | ::printf(" Aborted !\n"); 322 | endOfSearch = true; 323 | Timer::SleepMillis(1000); 324 | } 325 | } 326 | 327 | lastCount = count; 328 | lastGPUCount = gpuCount; 329 | t0 = t1; 330 | 331 | } 332 | 333 | count = getCPUCount() + getGPUCount(); 334 | t1 = Timer::get_tick(); 335 | 336 | if( !endOfSearch ) { 337 | printf("\r[%.2f %s][GPU %.2f %s][Cnt 2^%.2f][%s] ", 338 | avgKeyRate / 1000000.0,unit.c_str(), 339 | avgGpuKeyRate / 1000000.0,unit.c_str(), 340 | log2((double)count), 341 | GetTimeStr(t1 - startTime).c_str() 342 | ); 343 | } 344 | 345 | } 346 | 347 | -------------------------------------------------------------------------------- /Timer.cpp: -------------------------------------------------------------------------------- 1 | #include "Timer.h" 2 | 3 | static const char *prefix[] = { "","Kilo","Mega","Giga","Tera","Peta","Hexa" }; 4 | 5 | #ifdef WIN64 6 | 7 | LARGE_INTEGER Timer::perfTickStart; 8 | double Timer::perfTicksPerSec; 9 | LARGE_INTEGER Timer::qwTicksPerSec; 10 | #include 11 | 12 | #else 13 | 14 | #include 15 | #include 16 | #include 17 | time_t Timer::tickStart; 18 | 19 | #endif 20 | 21 | void Timer::Init() { 22 | 23 | #ifdef WIN64 24 | QueryPerformanceFrequency(&qwTicksPerSec); 25 | QueryPerformanceCounter(&perfTickStart); 26 | perfTicksPerSec = (double)qwTicksPerSec.QuadPart; 27 | #else 28 | tickStart=time(NULL); 29 | #endif 30 | 31 | } 32 | 33 | double Timer::get_tick() { 34 | 35 | #ifdef WIN64 36 | LARGE_INTEGER t, dt; 37 | QueryPerformanceCounter(&t); 38 | dt.QuadPart = t.QuadPart - perfTickStart.QuadPart; 39 | return (double)(dt.QuadPart) / perfTicksPerSec; 40 | #else 41 | struct timeval tv; 42 | gettimeofday(&tv, NULL); 43 | return (double)(tv.tv_sec - tickStart) + (double)tv.tv_usec / 1e6; 44 | #endif 45 | 46 | } 47 | 48 | uint32_t Timer::getSeed32() { 49 | return ::strtoul(getSeed(4).c_str(),NULL,16); 50 | } 51 | 52 | uint32_t Timer::getPID() { 53 | 54 | #ifdef WIN64 55 | return GetCurrentProcessId(); 56 | #else 57 | return (uint32_t)getpid(); 58 | #endif 59 | 60 | } 61 | 62 | std::string Timer::getSeed(int size) { 63 | 64 | std::string ret; 65 | char tmp[3]; 66 | unsigned char *buff = (unsigned char *)malloc(size); 67 | 68 | #ifdef WIN64 69 | 70 | HCRYPTPROV hCryptProv = NULL; 71 | LPCSTR UserName = "KeyContainer"; 72 | 73 | if (!CryptAcquireContext( 74 | &hCryptProv, // handle to the CSP 75 | UserName, // container name 76 | NULL, // use the default provider 77 | PROV_RSA_FULL, // provider type 78 | 0)) // flag values 79 | { 80 | //------------------------------------------------------------------- 81 | // An error occurred in acquiring the context. This could mean 82 | // that the key container requested does not exist. In this case, 83 | // the function can be called again to attempt to create a new key 84 | // container. Error codes are defined in Winerror.h. 85 | if (GetLastError() == NTE_BAD_KEYSET) { 86 | if (!CryptAcquireContext( 87 | &hCryptProv, 88 | UserName, 89 | NULL, 90 | PROV_RSA_FULL, 91 | CRYPT_NEWKEYSET)) { 92 | printf("CryptAcquireContext(): Could not create a new key container.\n"); 93 | exit(1); 94 | } 95 | } else { 96 | printf("CryptAcquireContext(): A cryptographic service handle could not be acquired.\n"); 97 | exit(1); 98 | } 99 | } 100 | 101 | if (!CryptGenRandom(hCryptProv,size,buff)) { 102 | printf("CryptGenRandom(): Error during random sequence acquisition.\n"); 103 | exit(1); 104 | } 105 | 106 | CryptReleaseContext(hCryptProv, 0); 107 | 108 | #else 109 | 110 | FILE *f = fopen("/dev/urandom","rb"); 111 | if(f==NULL) { 112 | printf("Failed to open /dev/urandom %s\n", strerror( errno )); 113 | exit(1); 114 | } 115 | if( fread(buff,1,size,f)!=size ) { 116 | printf("Failed to read from /dev/urandom %s\n", strerror( errno )); 117 | exit(1); 118 | } 119 | fclose(f); 120 | 121 | #endif 122 | 123 | for (int i = 0; i < size; i++) { 124 | sprintf(tmp,"%02X",buff[i]); 125 | ret.append(tmp); 126 | } 127 | 128 | free(buff); 129 | return ret; 130 | 131 | } 132 | 133 | 134 | std::string Timer::getResult(char *unit, int nbTry, double t0, double t1) { 135 | 136 | char tmp[256]; 137 | int pIdx = 0; 138 | double nbCallPerSec = (double)nbTry / (t1 - t0); 139 | while (nbCallPerSec > 1000.0 && pIdx < 5) { 140 | pIdx++; 141 | nbCallPerSec = nbCallPerSec / 1000.0; 142 | } 143 | sprintf(tmp, "%.3f %s%s/sec", nbCallPerSec, prefix[pIdx], unit); 144 | return std::string(tmp); 145 | 146 | } 147 | 148 | void Timer::printResult(char *unit, int nbTry, double t0, double t1) { 149 | 150 | printf("%s\n", getResult(unit, nbTry, t0, t1).c_str()); 151 | 152 | } 153 | 154 | int Timer::getCoreNumber() { 155 | 156 | #ifdef WIN64 157 | SYSTEM_INFO sysinfo; 158 | GetSystemInfo(&sysinfo); 159 | return sysinfo.dwNumberOfProcessors; 160 | #else 161 | return (size_t)sysconf(_SC_NPROCESSORS_ONLN); 162 | #endif 163 | 164 | } 165 | 166 | void Timer::SleepMillis(uint32_t millis) { 167 | 168 | #ifdef WIN64 169 | Sleep(millis); 170 | #else 171 | usleep(millis*1000); 172 | #endif 173 | 174 | } 175 | 176 | std::string Timer::getTS() { 177 | 178 | std::string ret; 179 | time_t now = time(NULL); 180 | char *time = ctime(&now); 181 | 182 | if(time[8]==' ') time[8]='0'; 183 | ret.push_back(time[8]); 184 | ret.push_back(time[9]); 185 | ret.push_back(time[4]); 186 | ret.push_back(time[5]); 187 | ret.push_back(time[6]); 188 | ret.push_back(time[22]); 189 | ret.push_back(time[23]); 190 | ret.push_back('_'); 191 | ret.push_back(time[11]); 192 | ret.push_back(time[12]); 193 | ret.push_back(time[14]); 194 | ret.push_back(time[15]); 195 | ret.push_back(time[17]); 196 | ret.push_back(time[18]); 197 | 198 | return ret; 199 | 200 | } 201 | -------------------------------------------------------------------------------- /Timer.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMERH 2 | #define TIMERH 3 | 4 | #include 5 | #include 6 | #ifdef WIN64 7 | #include 8 | #endif 9 | 10 | class Timer { 11 | 12 | public: 13 | static void Init(); 14 | static double get_tick(); 15 | static void printResult(char *unit, int nbTry, double t0, double t1); 16 | static std::string getResult(char *unit, int nbTry, double t0, double t1); 17 | static int getCoreNumber(); 18 | static std::string getSeed(int size); 19 | static void SleepMillis(uint32_t millis); 20 | static uint32_t getSeed32(); 21 | static uint32_t getPID(); 22 | static std::string getTS(); 23 | 24 | #ifdef WIN64 25 | static LARGE_INTEGER perfTickStart; 26 | static double perfTicksPerSec; 27 | static LARGE_INTEGER qwTicksPerSec; 28 | #else 29 | static time_t tickStart; 30 | #endif 31 | 32 | }; 33 | 34 | #endif // TIMERH 35 | -------------------------------------------------------------------------------- /VC_CUDA10/Kangaroo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.102 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Kangaroo", "Kangaroo.vcxproj", "{9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | ReleaseSM30|x64 = ReleaseSM30|x64 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Debug|x64.ActiveCfg = Debug|x64 16 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Debug|x64.Build.0 = Debug|x64 17 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Release|x64.ActiveCfg = Release|x64 18 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Release|x64.Build.0 = Release|x64 19 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.ReleaseSM30|x64.ActiveCfg = ReleaseSM30|x64 20 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.ReleaseSM30|x64.Build.0 = ReleaseSM30|x64 21 | EndGlobalSection 22 | GlobalSection(SolutionProperties) = preSolution 23 | HideSolutionNode = FALSE 24 | EndGlobalSection 25 | GlobalSection(ExtensibilityGlobals) = postSolution 26 | SolutionGuid = {6D720311-0075-4355-907B-9404246E4B51} 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /VC_CUDA10/Kangaroo.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | ReleaseSM30 10 | x64 11 | 12 | 13 | Release 14 | x64 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | compute_30,sm_30 51 | compute_30,sm_30;compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75; 52 | compute_61,sm_61 53 | true 54 | true 55 | compile 56 | 57 | 58 | 59 | 60 | 61 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A} 62 | VanitySearch 63 | 10.0.17763.0 64 | 65 | 66 | 67 | Application 68 | true 69 | MultiByte 70 | v141 71 | 72 | 73 | Application 74 | false 75 | true 76 | MultiByte 77 | v141 78 | 79 | 80 | Application 81 | false 82 | true 83 | MultiByte 84 | v141 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | true 102 | 103 | 104 | 105 | Level3 106 | Disabled 107 | WITHGPU;_CRT_SECURE_NO_WARNINGS;WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 108 | 109 | 110 | true 111 | Console 112 | cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies) 113 | 114 | 115 | 64 116 | 117 | 118 | 119 | 120 | Level3 121 | MaxSpeed 122 | true 123 | true 124 | WITHGPU;_CRT_SECURE_NO_WARNINGS;WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 125 | AnySuitable 126 | Speed 127 | 128 | 129 | true 130 | true 131 | true 132 | Console 133 | cudart_static.lib;kernel32.lib;user32.lib;ws2_32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 134 | 135 | 136 | 64 137 | 138 | 139 | 140 | 141 | Level3 142 | MaxSpeed 143 | true 144 | true 145 | WITHGPU;_CRT_SECURE_NO_WARNINGS;WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 146 | StreamingSIMDExtensions2 147 | 148 | 149 | true 150 | true 151 | true 152 | Console 153 | cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 154 | 155 | 156 | 64 157 | 158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /VC_CUDA10/Kangaroo.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | SECPK1 10 | 11 | 12 | SECPK1 13 | 14 | 15 | SECPK1 16 | 17 | 18 | SECPK1 19 | 20 | 21 | SECPK1 22 | 23 | 24 | SECPK1 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | SECPK1 37 | 38 | 39 | SECPK1 40 | 41 | 42 | SECPK1 43 | 44 | 45 | SECPK1 46 | 47 | 48 | SECPK1 49 | 50 | 51 | GPU 52 | 53 | 54 | GPU 55 | 56 | 57 | GPU 58 | 59 | 60 | 61 | 62 | 63 | 64 | {8caf15b2-3ab6-48c0-862b-ae72b7c23ca4} 65 | 66 | 67 | {71f0de0a-b083-42b0-ad08-2182418491f0} 68 | 69 | 70 | 71 | 72 | GPU 73 | 74 | 75 | -------------------------------------------------------------------------------- /VC_CUDA102/Kangaroo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.102 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Kangaroo", "Kangaroo.vcxproj", "{9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | ReleaseSM30|x64 = ReleaseSM30|x64 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Debug|x64.ActiveCfg = Debug|x64 16 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Debug|x64.Build.0 = Debug|x64 17 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Release|x64.ActiveCfg = Release|x64 18 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Release|x64.Build.0 = Release|x64 19 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.ReleaseSM30|x64.ActiveCfg = ReleaseSM30|x64 20 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.ReleaseSM30|x64.Build.0 = ReleaseSM30|x64 21 | EndGlobalSection 22 | GlobalSection(SolutionProperties) = preSolution 23 | HideSolutionNode = FALSE 24 | EndGlobalSection 25 | GlobalSection(ExtensibilityGlobals) = postSolution 26 | SolutionGuid = {6D720311-0075-4355-907B-9404246E4B51} 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /VC_CUDA102/Kangaroo.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | ReleaseSM30 10 | x64 11 | 12 | 13 | Release 14 | x64 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | compute_30,sm_30 53 | compute_30,sm_30;compute_35,sm_35;compute_37,sm_37;compute_50,sm_50;compute_52,sm_52;compute_60,sm_60;compute_61,sm_61;compute_70,sm_70;compute_75,sm_75; 54 | compute_61,sm_61 55 | true 56 | true 57 | compile 58 | 59 | 60 | 61 | 62 | 63 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A} 64 | Kangaroo 65 | 10.0 66 | 67 | 68 | 69 | Application 70 | true 71 | MultiByte 72 | v142 73 | 74 | 75 | Application 76 | false 77 | true 78 | MultiByte 79 | v142 80 | 81 | 82 | Application 83 | false 84 | true 85 | MultiByte 86 | v142 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | true 104 | 105 | 106 | 107 | Level3 108 | Disabled 109 | WITHGPU;_CRT_SECURE_NO_WARNINGS;WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 110 | MultiThreadedDebug 111 | 112 | 113 | true 114 | Console 115 | cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies) 116 | 117 | 118 | 64 119 | 120 | 121 | 122 | 123 | Level3 124 | MaxSpeed 125 | true 126 | true 127 | WITHGPU;_CRT_SECURE_NO_WARNINGS;WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 128 | AnySuitable 129 | Speed 130 | 131 | 132 | true 133 | true 134 | true 135 | Console 136 | cudart_static.lib;kernel32.lib;user32.lib;ws2_32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 137 | 138 | 139 | 64 140 | 141 | 142 | 143 | 144 | Level3 145 | MaxSpeed 146 | true 147 | true 148 | WITHGPU;_CRT_SECURE_NO_WARNINGS;WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 149 | StreamingSIMDExtensions2 150 | 151 | 152 | true 153 | true 154 | true 155 | Console 156 | cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 157 | 158 | 159 | 64 160 | 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /VC_CUDA102/Kangaroo.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | SECPK1 10 | 11 | 12 | SECPK1 13 | 14 | 15 | SECPK1 16 | 17 | 18 | SECPK1 19 | 20 | 21 | SECPK1 22 | 23 | 24 | SECPK1 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | SECPK1 39 | 40 | 41 | SECPK1 42 | 43 | 44 | SECPK1 45 | 46 | 47 | SECPK1 48 | 49 | 50 | SECPK1 51 | 52 | 53 | GPU 54 | 55 | 56 | GPU 57 | 58 | 59 | GPU 60 | 61 | 62 | 63 | 64 | 65 | 66 | {8caf15b2-3ab6-48c0-862b-ae72b7c23ca4} 67 | 68 | 69 | {71f0de0a-b083-42b0-ad08-2182418491f0} 70 | 71 | 72 | 73 | 74 | GPU 75 | 76 | 77 | -------------------------------------------------------------------------------- /VC_CUDA118/Kangaroo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32922.545 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Kangaroo", "Kangaroo.vcxproj", "{9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Debug|x64.ActiveCfg = Debug|x64 15 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Debug|x64.Build.0 = Debug|x64 16 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Release|x64.ActiveCfg = Release|x64 17 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {6D720311-0075-4355-907B-9404246E4B51} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /VC_CUDA118/Kangaroo.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | ReleaseSM30 10 | x64 11 | 12 | 13 | Release 14 | x64 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | compute_75,sm_75 53 | compute_75,sm_75; 54 | compute_61,sm_61 55 | true 56 | true 57 | compile 58 | 59 | 60 | 61 | 62 | 63 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A} 64 | Kangaroo 65 | 10.0 66 | 67 | 68 | 69 | Application 70 | true 71 | MultiByte 72 | v143 73 | 74 | 75 | Application 76 | false 77 | true 78 | MultiByte 79 | v143 80 | 81 | 82 | Application 83 | false 84 | true 85 | MultiByte 86 | v143 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | true 104 | 105 | 106 | 107 | Level3 108 | Disabled 109 | WITHGPU;_CRT_SECURE_NO_WARNINGS;WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 110 | MultiThreadedDebug 111 | 112 | 113 | true 114 | Console 115 | cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies) 116 | 117 | 118 | 64 119 | 120 | 121 | 122 | 123 | Level3 124 | MaxSpeed 125 | true 126 | true 127 | WITHGPU;_CRT_SECURE_NO_WARNINGS;WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 128 | AnySuitable 129 | Speed 130 | 131 | 132 | true 133 | true 134 | true 135 | Console 136 | cudart_static.lib;kernel32.lib;user32.lib;ws2_32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 137 | 138 | 139 | 64 140 | compute_75,sm_75 141 | 142 | 143 | 144 | 145 | Level3 146 | MaxSpeed 147 | true 148 | true 149 | WITHGPU;_CRT_SECURE_NO_WARNINGS;WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 150 | StreamingSIMDExtensions2 151 | 152 | 153 | true 154 | true 155 | true 156 | Console 157 | cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 158 | 159 | 160 | 64 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /VC_CUDA118/Kangaroo.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | SECPK1 10 | 11 | 12 | SECPK1 13 | 14 | 15 | SECPK1 16 | 17 | 18 | SECPK1 19 | 20 | 21 | SECPK1 22 | 23 | 24 | SECPK1 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | SECPK1 39 | 40 | 41 | SECPK1 42 | 43 | 44 | SECPK1 45 | 46 | 47 | SECPK1 48 | 49 | 50 | SECPK1 51 | 52 | 53 | GPU 54 | 55 | 56 | GPU 57 | 58 | 59 | GPU 60 | 61 | 62 | 63 | 64 | 65 | 66 | {8caf15b2-3ab6-48c0-862b-ae72b7c23ca4} 67 | 68 | 69 | {71f0de0a-b083-42b0-ad08-2182418491f0} 70 | 71 | 72 | 73 | 74 | GPU 75 | 76 | 77 | -------------------------------------------------------------------------------- /VC_CUDA8/Kangaroo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Kangaroo", "Kangaroo.vcxproj", "{9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Debug|x64.ActiveCfg = Debug|x64 15 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Debug|x64.Build.0 = Debug|x64 16 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Release|x64.ActiveCfg = Release|x64 17 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {6D720311-0075-4355-907B-9404246E4B51} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /VC_CUDA8/Kangaroo.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {9EA67A77-3F50-4FCE-85B9-FAB635FEFB0A} 23 | Kangaroo 24 | 25 | 26 | 27 | Application 28 | true 29 | MultiByte 30 | v140 31 | 32 | 33 | Application 34 | true 35 | MultiByte 36 | v140 37 | 38 | 39 | Application 40 | false 41 | true 42 | MultiByte 43 | v140 44 | 45 | 46 | Application 47 | false 48 | true 49 | MultiByte 50 | v140 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | true 71 | 72 | 73 | true 74 | 75 | 76 | 77 | Level3 78 | Disabled 79 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 80 | 81 | 82 | true 83 | Console 84 | cudart.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 85 | 86 | 87 | echo copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 88 | copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 89 | 90 | 91 | 92 | 93 | Level3 94 | Disabled 95 | _CRT_SECURE_NO_WARNINGS;WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 96 | Speed 97 | 98 | 99 | true 100 | Console 101 | cudart.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies) 102 | 103 | 104 | echo copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 105 | copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 106 | 107 | 108 | 64 109 | 110 | 111 | 112 | 113 | Level3 114 | MaxSpeed 115 | true 116 | true 117 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | 119 | 120 | true 121 | true 122 | true 123 | Console 124 | cudart.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 125 | 126 | 127 | echo copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 128 | copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 129 | 130 | 131 | 132 | 133 | Level3 134 | MaxSpeed 135 | false 136 | true 137 | WITHGPU;_CRT_SECURE_NO_WARNINGS;WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 138 | Speed 139 | AnySuitable 140 | true 141 | false 142 | MultiThreaded 143 | true 144 | StreamingSIMDExtensions 145 | 146 | 147 | true 148 | true 149 | true 150 | Console 151 | cudart.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies) 152 | 153 | 154 | echo copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 155 | copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 156 | 157 | 158 | 64 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | compute_20,sm_20 198 | 199 | 200 | 201 | 202 | 203 | 204 | -------------------------------------------------------------------------------- /VC_CUDA8/Kangaroo.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | SECPK1 11 | 12 | 13 | SECPK1 14 | 15 | 16 | SECPK1 17 | 18 | 19 | SECPK1 20 | 21 | 22 | SECPK1 23 | 24 | 25 | SECPK1 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | SECPK1 39 | 40 | 41 | SECPK1 42 | 43 | 44 | SECPK1 45 | 46 | 47 | SECPK1 48 | 49 | 50 | SECPK1 51 | 52 | 53 | GPU 54 | 55 | 56 | GPU 57 | 58 | 59 | GPU 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | {8caf15b2-3ab6-48c0-862b-ae72b7c23ca4} 70 | 71 | 72 | {71f0de0a-b083-42b0-ad08-2182418491f0} 73 | 74 | 75 | 76 | 77 | GPU 78 | 79 | 80 | -------------------------------------------------------------------------------- /WindowsErrors.h: -------------------------------------------------------------------------------- 1 | 2 | // WSA Error string 3 | typedef struct { 4 | int errCode; 5 | char *mesg; 6 | } WSAMAP; 7 | 8 | #define NBWSAERRORS 95 9 | 10 | WSAMAP WSAERRORS[] = { 11 | { /*WSA_INVALID_HANDLE*/6,"Specified event object handle is invalid" }, 12 | { /*WSA_NOT_ENOUGH_MEMORY*/8,"Insufficient memory available" }, 13 | { /*WSA_INVALID_PARAMETER*/87,"One or more parameters are invalid" }, 14 | { /*WSA_OPERATION_ABORTED*/995,"Overlapped operation aborted" }, 15 | { /*WSA_IO_INCOMPLETE*/996,"Overlapped I / O event object not in signaled state" }, 16 | { /*WSA_IO_PENDING*/997,"Overlapped operations will complete later" }, 17 | { WSAEINTR,"Interrupted function call" }, 18 | { WSAEBADF,"File handle is not valid" }, 19 | { WSAEACCES,"Permission denied" }, 20 | { WSAEFAULT,"Bad address" }, 21 | { WSAEINVAL,"Invalid argument" }, 22 | { WSAEMFILE,"Too many open files" }, 23 | { WSAEWOULDBLOCK,"Resource temporarily unavailable" }, 24 | { WSAEINPROGRESS,"Operation now in progress" }, 25 | { WSAEALREADY,"Operation already in progress" }, 26 | { WSAENOTSOCK,"Socket operation on nonsocket" }, 27 | { WSAEDESTADDRREQ,"Destination address required" }, 28 | { WSAEMSGSIZE,"Message too long" }, 29 | { WSAEPROTOTYPE,"Protocol wrong type for socket" }, 30 | { WSAENOPROTOOPT,"Bad protocol option" }, 31 | { WSAEPROTONOSUPPORT,"Protocol not supported" }, 32 | { WSAESOCKTNOSUPPORT,"Socket type not supported" }, 33 | { WSAEOPNOTSUPP,"Operation not supported" }, 34 | { WSAEPFNOSUPPORT,"Protocol family not supported" }, 35 | { WSAEAFNOSUPPORT,"Address family not supported by protocol family" }, 36 | { WSAEADDRINUSE,"Address already in use" }, 37 | { WSAEADDRNOTAVAIL,"Cannot assign requested address" }, 38 | { WSAENETDOWN,"Network is down" }, 39 | { WSAENETUNREACH,"Network is unreachable" }, 40 | { WSAENETRESET,"Network dropped connection on reset" }, 41 | { WSAECONNABORTED,"Software caused connection abort" }, 42 | { WSAECONNRESET,"Connection reset by peer" }, 43 | { WSAENOBUFS,"No buffer space available" }, 44 | { WSAEISCONN,"Socket is already connected" }, 45 | { WSAENOTCONN,"Socket is not connected" }, 46 | { WSAESHUTDOWN,"Cannot send after socket shutdown" }, 47 | { WSAETOOMANYREFS,"Too many references" }, 48 | { WSAETIMEDOUT,"Connection timed out" }, 49 | { WSAECONNREFUSED,"Connection refused" }, 50 | { WSAELOOP,"Cannot translate name" }, 51 | { WSAENAMETOOLONG,"Name too long" }, 52 | { WSAEHOSTDOWN,"Host is down" }, 53 | { WSAEHOSTUNREACH,"No route to host" }, 54 | { WSAENOTEMPTY,"Directory not empty" }, 55 | { WSAEPROCLIM,"Too many processes" }, 56 | { WSAEUSERS,"User quota exceeded" }, 57 | { WSAEDQUOT,"Disk quota exceeded" }, 58 | { WSAESTALE,"Stale file handle reference" }, 59 | { WSAEREMOTE,"Item is remote" }, 60 | { WSASYSNOTREADY,"Network subsystem is unavailable" }, 61 | { WSAVERNOTSUPPORTED,"Winsock.dll version out of range" }, 62 | { WSANOTINITIALISED,"Successful WSAStartup not yet performed" }, 63 | { WSAEDISCON,"Graceful shutdown in progress" }, 64 | { WSAENOMORE,"No more results" }, 65 | { WSAECANCELLED,"Call has been canceled" }, 66 | { WSAEINVALIDPROCTABLE,"Procedure call table is invalid" }, 67 | { WSAEINVALIDPROVIDER,"Service provider is invalid" }, 68 | { WSAEPROVIDERFAILEDINIT,"Service provider failed to initialize" }, 69 | { WSASYSCALLFAILURE,"System call failure" }, 70 | { WSASERVICE_NOT_FOUND,"Service not found" }, 71 | { WSATYPE_NOT_FOUND,"Class type not found" }, 72 | { WSA_E_NO_MORE,"No more results" }, 73 | { WSA_E_CANCELLED,"Call was canceled" }, 74 | { WSAEREFUSED,"Database query was refused" }, 75 | { WSAHOST_NOT_FOUND,"Host not found" }, 76 | { WSATRY_AGAIN,"Nonauthoritative host not found" }, 77 | { WSANO_RECOVERY,"This is a nonrecoverable error" }, 78 | { WSANO_DATA,"Valid name,no data record of requested type" }, 79 | { WSA_QOS_RECEIVERS,"QoS receivers" }, 80 | { WSA_QOS_SENDERS,"QoS senders" }, 81 | { WSA_QOS_NO_SENDERS,"No QoS senders" }, 82 | { WSA_QOS_NO_RECEIVERS,"QoS no receivers" }, 83 | { WSA_QOS_REQUEST_CONFIRMED,"QoS request confirmed" }, 84 | { WSA_QOS_ADMISSION_FAILURE,"QoS admission error" }, 85 | { WSA_QOS_POLICY_FAILURE,"QoS policy failure" }, 86 | { WSA_QOS_BAD_STYLE,"QoS bad style" }, 87 | { WSA_QOS_BAD_OBJECT,"QoS bad object" }, 88 | { WSA_QOS_TRAFFIC_CTRL_ERROR,"QoS traffic control error" }, 89 | { WSA_QOS_GENERIC_ERROR,"QoS generic error" }, 90 | { WSA_QOS_ESERVICETYPE,"QoS service type error" }, 91 | { WSA_QOS_EFLOWSPEC,"QoS flowspec error" }, 92 | { WSA_QOS_EPROVSPECBUF,"Invalid QoS provider buffer" }, 93 | { WSA_QOS_EFILTERSTYLE,"Invalid QoS filter style" }, 94 | { WSA_QOS_EFILTERTYPE,"Invalid QoS filter type" }, 95 | { WSA_QOS_EFILTERCOUNT,"Incorrect QoS filter count" }, 96 | { WSA_QOS_EOBJLENGTH,"Invalid QoS object length" }, 97 | { WSA_QOS_EFLOWCOUNT,"Incorrect QoS flow count" }, 98 | { WSA_QOS_EUNKOWNPSOBJ,"Unrecognized QoS object" }, 99 | { WSA_QOS_EPOLICYOBJ,"Invalid QoS policy object" }, 100 | { WSA_QOS_EFLOWDESC,"Invalid QoS flow descriptor" }, 101 | { WSA_QOS_EPSFLOWSPEC,"Invalid QoS provider - specific flowspec" }, 102 | { WSA_QOS_EPSFILTERSPEC,"Invalid QoS provider - specific filterspec" }, 103 | { WSA_QOS_ESDMODEOBJ,"Invalid QoS shape discard mode object" }, 104 | { WSA_QOS_ESHAPERATEOBJ,"Invalid QoS shaping rate object" }, 105 | { WSA_QOS_RESERVED_PETYPE,"Reserved policy QoS element type" } 106 | }; 107 | 108 | -------------------------------------------------------------------------------- /detect_cuda.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ccap="" 3 | cd deviceQuery 4 | echo "Attempting to autodetect CUDA compute capability..." 5 | make >cuda_build_log.txt 2>&1 && ccap=$(./deviceQuery | grep "CUDA Capability" | awk -F ' ' '{print $2}' | sort -n | head -n 1 | sed 's/\.//') 6 | if [ -n "${ccap}" ]; then 7 | echo "Detected ccap=${ccap}" 8 | else 9 | echo "Autodetection failed, falling back to ccap=30 (set the ccap variable to override this)" 10 | ccap="30" 11 | fi 12 | cd - 13 | echo ${ccap} > cuda_version.txt 14 | -------------------------------------------------------------------------------- /deviceQuery/Makefile: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # 3 | # Copyright 1993-2015 NVIDIA Corporation. All rights reserved. 4 | # 5 | # NOTICE TO USER: 6 | # 7 | # This source code is subject to NVIDIA ownership rights under U.S. and 8 | # international Copyright laws. 9 | # 10 | # NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE 11 | # CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR 12 | # IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH 13 | # REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF 14 | # MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. 15 | # IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, 16 | # OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 17 | # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 18 | # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE 19 | # OR PERFORMANCE OF THIS SOURCE CODE. 20 | # 21 | # U.S. Government End Users. This source code is a "commercial item" as 22 | # that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of 23 | # "commercial computer software" and "commercial computer software 24 | # documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) 25 | # and is provided to the U.S. Government only as a commercial end item. 26 | # Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through 27 | # 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the 28 | # source code with only those rights set forth herein. 29 | # 30 | ################################################################################ 31 | # 32 | # Makefile project only supported on Mac OS X and Linux Platforms) 33 | # 34 | ################################################################################ 35 | 36 | # Location of the CUDA Toolkit 37 | CUDA_PATH ?= /usr/local/cuda 38 | 39 | ############################## 40 | # start deprecated interface # 41 | ############################## 42 | ifeq ($(x86_64),1) 43 | $(info WARNING - x86_64 variable has been deprecated) 44 | $(info WARNING - please use TARGET_ARCH=x86_64 instead) 45 | TARGET_ARCH ?= x86_64 46 | endif 47 | ifeq ($(ARMv7),1) 48 | $(info WARNING - ARMv7 variable has been deprecated) 49 | $(info WARNING - please use TARGET_ARCH=armv7l instead) 50 | TARGET_ARCH ?= armv7l 51 | endif 52 | ifeq ($(aarch64),1) 53 | $(info WARNING - aarch64 variable has been deprecated) 54 | $(info WARNING - please use TARGET_ARCH=aarch64 instead) 55 | TARGET_ARCH ?= aarch64 56 | endif 57 | ifeq ($(ppc64le),1) 58 | $(info WARNING - ppc64le variable has been deprecated) 59 | $(info WARNING - please use TARGET_ARCH=ppc64le instead) 60 | TARGET_ARCH ?= ppc64le 61 | endif 62 | ifneq ($(GCC),) 63 | $(info WARNING - GCC variable has been deprecated) 64 | $(info WARNING - please use HOST_COMPILER=$(GCC) instead) 65 | HOST_COMPILER ?= $(GCC) 66 | endif 67 | ifneq ($(abi),) 68 | $(error ERROR - abi variable has been removed) 69 | endif 70 | ############################ 71 | # end deprecated interface # 72 | ############################ 73 | 74 | # architecture 75 | HOST_ARCH := $(shell uname -m) 76 | TARGET_ARCH ?= $(HOST_ARCH) 77 | ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le armv7l)) 78 | ifneq ($(TARGET_ARCH),$(HOST_ARCH)) 79 | ifneq (,$(filter $(TARGET_ARCH),x86_64 aarch64 sbsa ppc64le)) 80 | TARGET_SIZE := 64 81 | else ifneq (,$(filter $(TARGET_ARCH),armv7l)) 82 | TARGET_SIZE := 32 83 | endif 84 | else 85 | TARGET_SIZE := $(shell getconf LONG_BIT) 86 | endif 87 | else 88 | $(error ERROR - unsupported value $(TARGET_ARCH) for TARGET_ARCH!) 89 | endif 90 | 91 | # sbsa and aarch64 systems look similar. Need to differentiate them at host level for now. 92 | ifeq ($(HOST_ARCH),aarch64) 93 | ifeq ($(CUDA_PATH)/targets/sbsa-linux,$(shell ls -1d $(CUDA_PATH)/targets/sbsa-linux 2>/dev/null)) 94 | HOST_ARCH := sbsa 95 | TARGET_ARCH := sbsa 96 | endif 97 | endif 98 | 99 | ifneq ($(TARGET_ARCH),$(HOST_ARCH)) 100 | ifeq (,$(filter $(HOST_ARCH)-$(TARGET_ARCH),aarch64-armv7l x86_64-armv7l x86_64-aarch64 x86_64-sbsa x86_64-ppc64le)) 101 | $(error ERROR - cross compiling from $(HOST_ARCH) to $(TARGET_ARCH) is not supported!) 102 | endif 103 | endif 104 | 105 | # When on native aarch64 system with userspace of 32-bit, change TARGET_ARCH to armv7l 106 | ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_SIZE),aarch64-aarch64-32) 107 | TARGET_ARCH = armv7l 108 | endif 109 | 110 | # operating system 111 | HOST_OS := $(shell uname -s 2>/dev/null | tr "[:upper:]" "[:lower:]") 112 | TARGET_OS ?= $(HOST_OS) 113 | ifeq (,$(filter $(TARGET_OS),linux darwin qnx android)) 114 | $(error ERROR - unsupported value $(TARGET_OS) for TARGET_OS!) 115 | endif 116 | 117 | # host compiler 118 | ifeq ($(TARGET_OS),darwin) 119 | ifeq ($(shell expr `xcodebuild -version | grep -i xcode | awk '{print $$2}' | cut -d'.' -f1` \>= 5),1) 120 | HOST_COMPILER ?= clang++ 121 | endif 122 | else ifneq ($(TARGET_ARCH),$(HOST_ARCH)) 123 | ifeq ($(HOST_ARCH)-$(TARGET_ARCH),x86_64-armv7l) 124 | ifeq ($(TARGET_OS),linux) 125 | HOST_COMPILER ?= arm-linux-gnueabihf-g++ 126 | else ifeq ($(TARGET_OS),qnx) 127 | ifeq ($(QNX_HOST),) 128 | $(error ERROR - QNX_HOST must be passed to the QNX host toolchain) 129 | endif 130 | ifeq ($(QNX_TARGET),) 131 | $(error ERROR - QNX_TARGET must be passed to the QNX target toolchain) 132 | endif 133 | export QNX_HOST 134 | export QNX_TARGET 135 | HOST_COMPILER ?= $(QNX_HOST)/usr/bin/arm-unknown-nto-qnx6.6.0eabi-g++ 136 | else ifeq ($(TARGET_OS),android) 137 | HOST_COMPILER ?= arm-linux-androideabi-g++ 138 | endif 139 | else ifeq ($(TARGET_ARCH),aarch64) 140 | ifeq ($(TARGET_OS), linux) 141 | HOST_COMPILER ?= aarch64-linux-gnu-g++ 142 | else ifeq ($(TARGET_OS),qnx) 143 | ifeq ($(QNX_HOST),) 144 | $(error ERROR - QNX_HOST must be passed to the QNX host toolchain) 145 | endif 146 | ifeq ($(QNX_TARGET),) 147 | $(error ERROR - QNX_TARGET must be passed to the QNX target toolchain) 148 | endif 149 | export QNX_HOST 150 | export QNX_TARGET 151 | HOST_COMPILER ?= $(QNX_HOST)/usr/bin/q++ 152 | else ifeq ($(TARGET_OS), android) 153 | HOST_COMPILER ?= aarch64-linux-android-clang++ 154 | endif 155 | else ifeq ($(TARGET_ARCH),sbsa) 156 | HOST_COMPILER ?= aarch64-linux-gnu-g++ 157 | else ifeq ($(TARGET_ARCH),ppc64le) 158 | HOST_COMPILER ?= powerpc64le-linux-gnu-g++ 159 | endif 160 | endif 161 | HOST_COMPILER ?= g++ 162 | NVCC := $(CUDA_PATH)/bin/nvcc -ccbin $(HOST_COMPILER) 163 | 164 | # internal flags 165 | NVCCFLAGS := -m${TARGET_SIZE} 166 | CCFLAGS := 167 | LDFLAGS := 168 | 169 | # build flags 170 | ifeq ($(TARGET_OS),darwin) 171 | LDFLAGS += -rpath $(CUDA_PATH)/lib 172 | CCFLAGS += -arch $(HOST_ARCH) 173 | else ifeq ($(HOST_ARCH)-$(TARGET_ARCH)-$(TARGET_OS),x86_64-armv7l-linux) 174 | LDFLAGS += --dynamic-linker=/lib/ld-linux-armhf.so.3 175 | CCFLAGS += -mfloat-abi=hard 176 | else ifeq ($(TARGET_OS),android) 177 | LDFLAGS += -pie 178 | CCFLAGS += -fpie -fpic -fexceptions 179 | endif 180 | 181 | ifneq ($(TARGET_ARCH),$(HOST_ARCH)) 182 | ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux) 183 | ifneq ($(TARGET_FS),) 184 | GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6) 185 | ifeq ($(GCCVERSIONLTEQ46),1) 186 | CCFLAGS += --sysroot=$(TARGET_FS) 187 | endif 188 | LDFLAGS += --sysroot=$(TARGET_FS) 189 | LDFLAGS += -rpath-link=$(TARGET_FS)/lib 190 | LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib 191 | LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/arm-linux-gnueabihf 192 | endif 193 | endif 194 | ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux) 195 | ifneq ($(TARGET_FS),) 196 | GCCVERSIONLTEQ46 := $(shell expr `$(HOST_COMPILER) -dumpversion` \<= 4.6) 197 | ifeq ($(GCCVERSIONLTEQ46),1) 198 | CCFLAGS += --sysroot=$(TARGET_FS) 199 | endif 200 | LDFLAGS += --sysroot=$(TARGET_FS) 201 | LDFLAGS += -rpath-link=$(TARGET_FS)/lib -L$(TARGET_FS)/lib 202 | LDFLAGS += -rpath-link=$(TARGET_FS)/lib/aarch64-linux-gnu -L$(TARGET_FS)/lib/aarch64-linux-gnu 203 | LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib -L$(TARGET_FS)/usr/lib 204 | LDFLAGS += -rpath-link=$(TARGET_FS)/usr/lib/aarch64-linux-gnu -L$(TARGET_FS)/usr/lib/aarch64-linux-gnu 205 | LDFLAGS += --unresolved-symbols=ignore-in-shared-libs 206 | CCFLAGS += -isystem=$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include -I$(TARGET_FS)/usr/include/libdrm 207 | CCFLAGS += -isystem=$(TARGET_FS)/usr/include/aarch64-linux-gnu -I$(TARGET_FS)/usr/include/aarch64-linux-gnu 208 | endif 209 | endif 210 | ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx) 211 | NVCCFLAGS += --qpp-config 5.4.0,gcc_ntoaarch64le 212 | CCFLAGS += -DWIN_INTERFACE_CUSTOM -I/usr/include/aarch64-qnx-gnu 213 | LDFLAGS += -lsocket 214 | LDFLAGS += -L/usr/lib/aarch64-qnx-gnu 215 | CCFLAGS += "-Wl\,-rpath-link\,/usr/lib/aarch64-qnx-gnu" 216 | ifdef TARGET_OVERRIDE 217 | LDFLAGS += -lslog2 218 | endif 219 | 220 | ifneq ($(TARGET_FS),) 221 | LDFLAGS += -L$(TARGET_FS)/usr/lib 222 | CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/lib" 223 | LDFLAGS += -L$(TARGET_FS)/usr/libnvidia 224 | CCFLAGS += "-Wl\,-rpath-link\,$(TARGET_FS)/usr/libnvidia" 225 | endif 226 | endif 227 | endif 228 | 229 | ifdef TARGET_OVERRIDE # cuda toolkit targets override 230 | NVCCFLAGS += -target-dir $(TARGET_OVERRIDE) 231 | endif 232 | 233 | # Install directory of different arch 234 | CUDA_INSTALL_TARGET_DIR := 235 | ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-linux) 236 | CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-gnueabihf/ 237 | else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-linux) 238 | CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux/ 239 | else ifeq ($(TARGET_ARCH)-$(TARGET_OS),sbsa-linux) 240 | CUDA_INSTALL_TARGET_DIR = targets/sbsa-linux/ 241 | else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-android) 242 | CUDA_INSTALL_TARGET_DIR = targets/armv7-linux-androideabi/ 243 | else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-android) 244 | CUDA_INSTALL_TARGET_DIR = targets/aarch64-linux-androideabi/ 245 | else ifeq ($(TARGET_ARCH)-$(TARGET_OS),armv7l-qnx) 246 | CUDA_INSTALL_TARGET_DIR = targets/ARMv7-linux-QNX/ 247 | else ifeq ($(TARGET_ARCH)-$(TARGET_OS),aarch64-qnx) 248 | CUDA_INSTALL_TARGET_DIR = targets/aarch64-qnx/ 249 | else ifeq ($(TARGET_ARCH),ppc64le) 250 | CUDA_INSTALL_TARGET_DIR = targets/ppc64le-linux/ 251 | endif 252 | 253 | # Debug build flags 254 | ifeq ($(dbg),1) 255 | NVCCFLAGS += -g -G 256 | BUILD_TYPE := debug 257 | else 258 | BUILD_TYPE := release 259 | endif 260 | 261 | ALL_CCFLAGS := 262 | ALL_CCFLAGS += $(NVCCFLAGS) 263 | ALL_CCFLAGS += $(EXTRA_NVCCFLAGS) 264 | ALL_CCFLAGS += $(addprefix -Xcompiler ,$(CCFLAGS)) 265 | ALL_CCFLAGS += $(addprefix -Xcompiler ,$(EXTRA_CCFLAGS)) 266 | 267 | SAMPLE_ENABLED := 1 268 | 269 | ALL_LDFLAGS := 270 | ALL_LDFLAGS += $(ALL_CCFLAGS) 271 | ALL_LDFLAGS += $(addprefix -Xlinker ,$(LDFLAGS)) 272 | ALL_LDFLAGS += $(addprefix -Xlinker ,$(EXTRA_LDFLAGS)) 273 | 274 | # Common includes and paths for CUDA 275 | INCLUDES := -I./inc 276 | LIBRARIES := 277 | 278 | ################################################################################ 279 | 280 | # Gencode arguments 281 | SMS ?= 35 37 50 52 60 61 70 75 80 86 282 | 283 | ifeq ($(SMS),) 284 | $(info >>> WARNING - no SM architectures have been specified - waiving sample <<<) 285 | SAMPLE_ENABLED := 0 286 | endif 287 | 288 | ifeq ($(GENCODE_FLAGS),) 289 | # Generate SASS code for each SM architecture listed in $(SMS) 290 | $(foreach sm,$(SMS),$(eval GENCODE_FLAGS += -gencode arch=compute_$(sm),code=sm_$(sm))) 291 | 292 | # Generate PTX code from the highest SM architecture in $(SMS) to guarantee forward-compatibility 293 | HIGHEST_SM := $(lastword $(sort $(SMS))) 294 | ifneq ($(HIGHEST_SM),) 295 | GENCODE_FLAGS += -gencode arch=compute_$(HIGHEST_SM),code=compute_$(HIGHEST_SM) 296 | endif 297 | endif 298 | 299 | ALL_CCFLAGS += --threads 0 300 | 301 | ifeq ($(SAMPLE_ENABLED),0) 302 | EXEC ?= @echo "[@]" 303 | endif 304 | 305 | ################################################################################ 306 | 307 | # Target rules 308 | all: build 309 | 310 | build: deviceQuery 311 | 312 | check.deps: 313 | ifeq ($(SAMPLE_ENABLED),0) 314 | @echo "Sample will be waived due to the above missing dependencies" 315 | else 316 | @echo "Sample is ready - all dependencies have been met" 317 | endif 318 | 319 | deviceQuery.o:deviceQuery.cpp 320 | $(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $@ -c $< 321 | 322 | deviceQuery: deviceQuery.o 323 | $(EXEC) $(NVCC) $(ALL_LDFLAGS) $(GENCODE_FLAGS) -o $@ $+ $(LIBRARIES) 324 | 325 | run: build 326 | $(EXEC) ./deviceQuery 327 | 328 | clean: 329 | rm -f deviceQuery deviceQuery.o 330 | 331 | clobber: clean 332 | -------------------------------------------------------------------------------- /deviceQuery/NsightEclipse.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | deviceQuery 5 | 6 | cudaSetDevice 7 | cudaGetDeviceCount 8 | cudaGetDeviceProperties 9 | cudaDriverGetVersion 10 | cudaRuntimeGetVersion 11 | 12 | 13 | whole 14 | 15 | ./ 16 | ../ 17 | ../../common/inc 18 | 19 | 20 | CUDA Runtime API 21 | Device Query 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | true 30 | deviceQuery.cpp 31 | 32 | 1:CUDA Basic Topics 33 | 34 | sm35 35 | sm37 36 | sm50 37 | sm52 38 | sm60 39 | sm61 40 | sm70 41 | sm75 42 | sm80 43 | sm86 44 | 45 | 46 | x86_64 47 | linux 48 | 49 | 50 | windows7 51 | 52 | 53 | x86_64 54 | macosx 55 | 56 | 57 | arm 58 | 59 | 60 | ppc64le 61 | linux 62 | 63 | 64 | 65 | all 66 | 67 | Device Query 68 | exe 69 | 70 | -------------------------------------------------------------------------------- /deviceQuery/deviceQuery: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikorist/Kangaroo-256-bit/0e1b51eac833fa722339f044ea86b7c1bf2f412c/deviceQuery/deviceQuery -------------------------------------------------------------------------------- /deviceQuery/deviceQuery.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1993-2015 NVIDIA Corporation. All rights reserved. 3 | * 4 | * Please refer to the NVIDIA end user license agreement (EULA) associated 5 | * with this source code for terms and conditions that govern your use of 6 | * this software. Any use, reproduction, disclosure, or distribution of 7 | * this software and related documentation outside the terms of the EULA 8 | * is strictly prohibited. 9 | * 10 | */ 11 | /* This sample queries the properties of the CUDA devices present in the system 12 | * via CUDA Runtime API. */ 13 | 14 | // std::system includes 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | int *pArgc = NULL; 24 | char **pArgv = NULL; 25 | 26 | #if CUDART_VERSION < 5000 27 | 28 | // CUDA-C includes 29 | #include 30 | 31 | // This function wraps the CUDA Driver API into a template function 32 | template 33 | inline void getCudaAttribute(T *attribute, CUdevice_attribute device_attribute, 34 | int device) { 35 | CUresult error = cuDeviceGetAttribute(attribute, device_attribute, device); 36 | 37 | if (CUDA_SUCCESS != error) { 38 | fprintf( 39 | stderr, 40 | "cuSafeCallNoSync() Driver API error = %04d from file <%s>, line %i.\n", 41 | error, __FILE__, __LINE__); 42 | 43 | exit(EXIT_FAILURE); 44 | } 45 | } 46 | 47 | #endif /* CUDART_VERSION < 5000 */ 48 | 49 | //////////////////////////////////////////////////////////////////////////////// 50 | // Program main 51 | //////////////////////////////////////////////////////////////////////////////// 52 | int main(int argc, char **argv) { 53 | pArgc = &argc; 54 | pArgv = argv; 55 | 56 | printf("%s Starting...\n\n", argv[0]); 57 | printf( 58 | " CUDA Device Query (Runtime API) version (CUDART static linking)\n\n"); 59 | 60 | int deviceCount = 0; 61 | cudaError_t error_id = cudaGetDeviceCount(&deviceCount); 62 | 63 | if (error_id != cudaSuccess) { 64 | printf("cudaGetDeviceCount returned %d\n-> %s\n", 65 | static_cast(error_id), cudaGetErrorString(error_id)); 66 | printf("Result = FAIL\n"); 67 | exit(EXIT_FAILURE); 68 | } 69 | 70 | // This function call returns 0 if there are no CUDA capable devices. 71 | if (deviceCount == 0) { 72 | printf("There are no available device(s) that support CUDA\n"); 73 | } else { 74 | printf("Detected %d CUDA Capable device(s)\n", deviceCount); 75 | } 76 | 77 | int dev, driverVersion = 0, runtimeVersion = 0; 78 | 79 | for (dev = 0; dev < deviceCount; ++dev) { 80 | cudaSetDevice(dev); 81 | cudaDeviceProp deviceProp; 82 | cudaGetDeviceProperties(&deviceProp, dev); 83 | 84 | printf("\nDevice %d: \"%s\"\n", dev, deviceProp.name); 85 | 86 | // Console log 87 | cudaDriverGetVersion(&driverVersion); 88 | cudaRuntimeGetVersion(&runtimeVersion); 89 | printf(" CUDA Driver Version / Runtime Version %d.%d / %d.%d\n", 90 | driverVersion / 1000, (driverVersion % 100) / 10, 91 | runtimeVersion / 1000, (runtimeVersion % 100) / 10); 92 | printf(" CUDA Capability Major/Minor version number: %d.%d\n", 93 | deviceProp.major, deviceProp.minor); 94 | 95 | char msg[256]; 96 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 97 | sprintf_s(msg, sizeof(msg), 98 | " Total amount of global memory: %.0f MBytes " 99 | "(%llu bytes)\n", 100 | static_cast(deviceProp.totalGlobalMem / 1048576.0f), 101 | (unsigned long long)deviceProp.totalGlobalMem); 102 | #else 103 | snprintf(msg, sizeof(msg), 104 | " Total amount of global memory: %.0f MBytes " 105 | "(%llu bytes)\n", 106 | static_cast(deviceProp.totalGlobalMem / 1048576.0f), 107 | (unsigned long long)deviceProp.totalGlobalMem); 108 | #endif 109 | printf("%s", msg); 110 | 111 | printf(" (%2d) Multiprocessors, (%3d) CUDA Cores/MP: %d CUDA Cores\n", 112 | deviceProp.multiProcessorCount, 113 | _ConvertSMVer2Cores(deviceProp.major, deviceProp.minor), 114 | _ConvertSMVer2Cores(deviceProp.major, deviceProp.minor) * 115 | deviceProp.multiProcessorCount); 116 | printf( 117 | " GPU Max Clock rate: %.0f MHz (%0.2f " 118 | "GHz)\n", 119 | deviceProp.clockRate * 1e-3f, deviceProp.clockRate * 1e-6f); 120 | 121 | #if CUDART_VERSION >= 5000 122 | // This is supported in CUDA 5.0 (runtime API device properties) 123 | printf(" Memory Clock rate: %.0f Mhz\n", 124 | deviceProp.memoryClockRate * 1e-3f); 125 | printf(" Memory Bus Width: %d-bit\n", 126 | deviceProp.memoryBusWidth); 127 | 128 | if (deviceProp.l2CacheSize) { 129 | printf(" L2 Cache Size: %d bytes\n", 130 | deviceProp.l2CacheSize); 131 | } 132 | 133 | #else 134 | // This only available in CUDA 4.0-4.2 (but these were only exposed in the 135 | // CUDA Driver API) 136 | int memoryClock; 137 | getCudaAttribute(&memoryClock, CU_DEVICE_ATTRIBUTE_MEMORY_CLOCK_RATE, 138 | dev); 139 | printf(" Memory Clock rate: %.0f Mhz\n", 140 | memoryClock * 1e-3f); 141 | int memBusWidth; 142 | getCudaAttribute(&memBusWidth, 143 | CU_DEVICE_ATTRIBUTE_GLOBAL_MEMORY_BUS_WIDTH, dev); 144 | printf(" Memory Bus Width: %d-bit\n", 145 | memBusWidth); 146 | int L2CacheSize; 147 | getCudaAttribute(&L2CacheSize, CU_DEVICE_ATTRIBUTE_L2_CACHE_SIZE, dev); 148 | 149 | if (L2CacheSize) { 150 | printf(" L2 Cache Size: %d bytes\n", 151 | L2CacheSize); 152 | } 153 | 154 | #endif 155 | 156 | printf( 157 | " Maximum Texture Dimension Size (x,y,z) 1D=(%d), 2D=(%d, " 158 | "%d), 3D=(%d, %d, %d)\n", 159 | deviceProp.maxTexture1D, deviceProp.maxTexture2D[0], 160 | deviceProp.maxTexture2D[1], deviceProp.maxTexture3D[0], 161 | deviceProp.maxTexture3D[1], deviceProp.maxTexture3D[2]); 162 | printf( 163 | " Maximum Layered 1D Texture Size, (num) layers 1D=(%d), %d layers\n", 164 | deviceProp.maxTexture1DLayered[0], deviceProp.maxTexture1DLayered[1]); 165 | printf( 166 | " Maximum Layered 2D Texture Size, (num) layers 2D=(%d, %d), %d " 167 | "layers\n", 168 | deviceProp.maxTexture2DLayered[0], deviceProp.maxTexture2DLayered[1], 169 | deviceProp.maxTexture2DLayered[2]); 170 | 171 | printf(" Total amount of constant memory: %zu bytes\n", 172 | deviceProp.totalConstMem); 173 | printf(" Total amount of shared memory per block: %zu bytes\n", 174 | deviceProp.sharedMemPerBlock); 175 | printf(" Total shared memory per multiprocessor: %zu bytes\n", 176 | deviceProp.sharedMemPerMultiprocessor); 177 | printf(" Total number of registers available per block: %d\n", 178 | deviceProp.regsPerBlock); 179 | printf(" Warp size: %d\n", 180 | deviceProp.warpSize); 181 | printf(" Maximum number of threads per multiprocessor: %d\n", 182 | deviceProp.maxThreadsPerMultiProcessor); 183 | printf(" Maximum number of threads per block: %d\n", 184 | deviceProp.maxThreadsPerBlock); 185 | printf(" Max dimension size of a thread block (x,y,z): (%d, %d, %d)\n", 186 | deviceProp.maxThreadsDim[0], deviceProp.maxThreadsDim[1], 187 | deviceProp.maxThreadsDim[2]); 188 | printf(" Max dimension size of a grid size (x,y,z): (%d, %d, %d)\n", 189 | deviceProp.maxGridSize[0], deviceProp.maxGridSize[1], 190 | deviceProp.maxGridSize[2]); 191 | printf(" Maximum memory pitch: %zu bytes\n", 192 | deviceProp.memPitch); 193 | printf(" Texture alignment: %zu bytes\n", 194 | deviceProp.textureAlignment); 195 | printf( 196 | " Concurrent copy and kernel execution: %s with %d copy " 197 | "engine(s)\n", 198 | (deviceProp.deviceOverlap ? "Yes" : "No"), deviceProp.asyncEngineCount); 199 | printf(" Run time limit on kernels: %s\n", 200 | deviceProp.kernelExecTimeoutEnabled ? "Yes" : "No"); 201 | printf(" Integrated GPU sharing Host Memory: %s\n", 202 | deviceProp.integrated ? "Yes" : "No"); 203 | printf(" Support host page-locked memory mapping: %s\n", 204 | deviceProp.canMapHostMemory ? "Yes" : "No"); 205 | printf(" Alignment requirement for Surfaces: %s\n", 206 | deviceProp.surfaceAlignment ? "Yes" : "No"); 207 | printf(" Device has ECC support: %s\n", 208 | deviceProp.ECCEnabled ? "Enabled" : "Disabled"); 209 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 210 | printf(" CUDA Device Driver Mode (TCC or WDDM): %s\n", 211 | deviceProp.tccDriver ? "TCC (Tesla Compute Cluster Driver)" 212 | : "WDDM (Windows Display Driver Model)"); 213 | #endif 214 | printf(" Device supports Unified Addressing (UVA): %s\n", 215 | deviceProp.unifiedAddressing ? "Yes" : "No"); 216 | printf(" Device supports Managed Memory: %s\n", 217 | deviceProp.managedMemory ? "Yes" : "No"); 218 | printf(" Device supports Compute Preemption: %s\n", 219 | deviceProp.computePreemptionSupported ? "Yes" : "No"); 220 | printf(" Supports Cooperative Kernel Launch: %s\n", 221 | deviceProp.cooperativeLaunch ? "Yes" : "No"); 222 | printf(" Supports MultiDevice Co-op Kernel Launch: %s\n", 223 | deviceProp.cooperativeMultiDeviceLaunch ? "Yes" : "No"); 224 | printf(" Device PCI Domain ID / Bus ID / location ID: %d / %d / %d\n", 225 | deviceProp.pciDomainID, deviceProp.pciBusID, deviceProp.pciDeviceID); 226 | 227 | const char *sComputeMode[] = { 228 | "Default (multiple host threads can use ::cudaSetDevice() with device " 229 | "simultaneously)", 230 | "Exclusive (only one host thread in one process is able to use " 231 | "::cudaSetDevice() with this device)", 232 | "Prohibited (no host thread can use ::cudaSetDevice() with this " 233 | "device)", 234 | "Exclusive Process (many threads in one process is able to use " 235 | "::cudaSetDevice() with this device)", 236 | "Unknown", 237 | NULL}; 238 | printf(" Compute Mode:\n"); 239 | printf(" < %s >\n", sComputeMode[deviceProp.computeMode]); 240 | } 241 | 242 | // If there are 2 or more GPUs, query to determine whether RDMA is supported 243 | if (deviceCount >= 2) { 244 | cudaDeviceProp prop[64]; 245 | int gpuid[64]; // we want to find the first two GPUs that can support P2P 246 | int gpu_p2p_count = 0; 247 | 248 | for (int i = 0; i < deviceCount; i++) { 249 | checkCudaErrors(cudaGetDeviceProperties(&prop[i], i)); 250 | 251 | // Only boards based on Fermi or later can support P2P 252 | if ((prop[i].major >= 2) 253 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 254 | // on Windows (64-bit), the Tesla Compute Cluster driver for windows 255 | // must be enabled to support this 256 | && prop[i].tccDriver 257 | #endif 258 | ) { 259 | // This is an array of P2P capable GPUs 260 | gpuid[gpu_p2p_count++] = i; 261 | } 262 | } 263 | 264 | // Show all the combinations of support P2P GPUs 265 | int can_access_peer; 266 | 267 | if (gpu_p2p_count >= 2) { 268 | for (int i = 0; i < gpu_p2p_count; i++) { 269 | for (int j = 0; j < gpu_p2p_count; j++) { 270 | if (gpuid[i] == gpuid[j]) { 271 | continue; 272 | } 273 | checkCudaErrors( 274 | cudaDeviceCanAccessPeer(&can_access_peer, gpuid[i], gpuid[j])); 275 | printf("> Peer access from %s (GPU%d) -> %s (GPU%d) : %s\n", 276 | prop[gpuid[i]].name, gpuid[i], prop[gpuid[j]].name, gpuid[j], 277 | can_access_peer ? "Yes" : "No"); 278 | } 279 | } 280 | } 281 | } 282 | 283 | // csv masterlog info 284 | // ***************************** 285 | // exe and CUDA driver name 286 | printf("\n"); 287 | std::string sProfileString = "deviceQuery, CUDA Driver = CUDART"; 288 | char cTemp[16]; 289 | 290 | // driver version 291 | sProfileString += ", CUDA Driver Version = "; 292 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 293 | sprintf_s(cTemp, 10, "%d.%d", driverVersion/1000, (driverVersion%100)/10); 294 | #else 295 | snprintf(cTemp, sizeof(cTemp), "%d.%d", driverVersion / 1000, 296 | (driverVersion % 100) / 10); 297 | #endif 298 | sProfileString += cTemp; 299 | 300 | // Runtime version 301 | sProfileString += ", CUDA Runtime Version = "; 302 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 303 | sprintf_s(cTemp, 10, "%d.%d", runtimeVersion/1000, (runtimeVersion%100)/10); 304 | #else 305 | snprintf(cTemp, sizeof(cTemp), "%d.%d", runtimeVersion / 1000, 306 | (runtimeVersion % 100) / 10); 307 | #endif 308 | sProfileString += cTemp; 309 | 310 | // Device count 311 | sProfileString += ", NumDevs = "; 312 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 313 | sprintf_s(cTemp, 10, "%d", deviceCount); 314 | #else 315 | snprintf(cTemp, sizeof(cTemp), "%d", deviceCount); 316 | #endif 317 | sProfileString += cTemp; 318 | sProfileString += "\n"; 319 | printf("%s", sProfileString.c_str()); 320 | 321 | printf("Result = PASS\n"); 322 | 323 | // finish 324 | exit(EXIT_SUCCESS); 325 | } 326 | -------------------------------------------------------------------------------- /deviceQuery/readme.txt: -------------------------------------------------------------------------------- 1 | Sample: deviceQuery 2 | Minimum spec: SM 3.5 3 | 4 | This sample enumerates the properties of the CUDA devices present in the system. 5 | 6 | Key concepts: 7 | CUDA Runtime API 8 | Device Query 9 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "GPU/GPUEngine.h" 9 | #include "Kangaroo.h" 10 | #include "SECPK1/SECP256k1.h" 11 | #include "Timer.h" 12 | 13 | using namespace std; 14 | 15 | #define CHECKARG(opt, n) \ 16 | if (a >= argc - 1) { \ 17 | ::printf(opt " missing argument #%d\n", n); \ 18 | exit(0); \ 19 | } else { \ 20 | a++; \ 21 | } 22 | 23 | // ------------------------------------------------------------------------------------------ 24 | 25 | void printUsage() { 26 | printf("Kangaroo-256 [-v] [-t nbThread] [-d dpBit] [gpu] [-check]\n"); 27 | printf(" [-gpuId gpuId1[,gpuId2,...]] [-g g1x,g1y[,g2x,g2y,...]]\n"); 28 | printf(" inFile\n"); 29 | printf(" -v: Print version\n"); 30 | printf(" -gpu: Enable gpu calculation\n"); 31 | printf(" -gpuId gpuId1,gpuId2,...: List of GPU(s) to use, default is 0\n"); 32 | printf( 33 | " -g g1x,g1y,g2x,g2y,...: Specify GPU(s) kernel gridsize, default is " 34 | "2*(MP),2*(Core/MP)\n"); 35 | printf( 36 | " -d: Specify number of leading zeros for the DP method (default is " 37 | "auto)\n"); 38 | printf(" -t nbThread: Secify number of thread\n"); 39 | printf( 40 | " -w workfile: Specify file to save work into (current processed key " 41 | "only)\n"); 42 | printf( 43 | " -i workfile: Specify file to load work from (current processed key " 44 | "only)\n"); 45 | printf(" -wi workInterval: Periodic interval (in seconds) for saving work\n"); 46 | printf(" -ws: Save kangaroos in the work file\n"); 47 | printf(" -wss: Save kangaroos via the server\n"); 48 | printf(" -wsplit: Split work file of server and reset hashtable\n"); 49 | printf(" -wm file1 file2 destfile: Merge work file\n"); 50 | printf(" -wmdir dir destfile: Merge directory of work files\n"); 51 | printf(" -wt timeout: Save work timeout in millisec (default is 3000ms)\n"); 52 | printf(" -winfo file1: Work file info file\n"); 53 | printf( 54 | " -wpartcreate name: Create empty partitioned work file (name is a " 55 | "directory)\n"); 56 | printf(" -wcheck worfile: Check workfile integrity\n"); 57 | printf( 58 | " -m maxStep: number of operations before give up the search " 59 | "(maxStep*expected operation)\n"); 60 | printf(" -s: Start in server mode\n"); 61 | printf( 62 | " -c server_ip: Start in client mode and connect to server server_ip\n"); 63 | printf(" -sp port: Server port, default is 17403\n"); 64 | printf(" -nt timeout: Network timeout in millisec (default is 3000ms)\n"); 65 | printf(" -o fileName: output result to fileName\n"); 66 | printf(" -l: List cuda enabled devices\n"); 67 | printf(" -check: Check GPU kernel vs CPU\n"); 68 | printf(" inFile: intput configuration file\n"); 69 | exit(0); 70 | } 71 | 72 | // ------------------------------------------------------------------------------------------ 73 | 74 | int getInt(string name, char *v) { 75 | int r; 76 | 77 | try { 78 | r = std::stoi(string(v)); 79 | 80 | } catch (std::invalid_argument &) { 81 | printf("Invalid %s argument, number expected\n", name.c_str()); 82 | exit(-1); 83 | } 84 | 85 | return r; 86 | } 87 | 88 | double getDouble(string name, char *v) { 89 | double r; 90 | 91 | try { 92 | r = std::stod(string(v)); 93 | 94 | } catch (std::invalid_argument &) { 95 | printf("Invalid %s argument, number expected\n", name.c_str()); 96 | exit(-1); 97 | } 98 | 99 | return r; 100 | } 101 | 102 | // ------------------------------------------------------------------------------------------ 103 | 104 | void getInts(string name, vector &tokens, const string &text, char sep) { 105 | size_t start = 0, end = 0; 106 | tokens.clear(); 107 | int item; 108 | 109 | try { 110 | while ((end = text.find(sep, start)) != string::npos) { 111 | item = std::stoi(text.substr(start, end - start)); 112 | tokens.push_back(item); 113 | start = end + 1; 114 | } 115 | 116 | item = std::stoi(text.substr(start)); 117 | tokens.push_back(item); 118 | 119 | } catch (std::invalid_argument &) { 120 | printf("Invalid %s argument, number expected\n", name.c_str()); 121 | exit(-1); 122 | } 123 | } 124 | // ------------------------------------------------------------------------------------------ 125 | 126 | // Default params 127 | static int dp = -1; 128 | static int nbCPUThread; 129 | static string configFile = ""; 130 | static bool checkFlag = false; 131 | static bool gpuEnable = false; 132 | static vector gpuId = {0}; 133 | static vector gridSize; 134 | static string workFile = ""; 135 | static string checkWorkFile = ""; 136 | static string iWorkFile = ""; 137 | static uint32_t savePeriod = 60; 138 | static bool saveKangaroo = false; 139 | static bool saveKangarooByServer = false; 140 | static string merge1 = ""; 141 | static string merge2 = ""; 142 | static string mergeDest = ""; 143 | static string mergeDir = ""; 144 | static string infoFile = ""; 145 | static double maxStep = 0.0; 146 | static int wtimeout = 3000; 147 | static int ntimeout = 3000; 148 | static int port = 17403; 149 | static bool serverMode = false; 150 | static string serverIP = ""; 151 | static string outputFile = "KEYFOUNDKEYFOUND.txt"; 152 | static bool splitWorkFile = false; 153 | 154 | int main(int argc, char *argv[]) { 155 | std::system("clear"); 156 | time_t currentTime = time(nullptr); 157 | #ifdef USE_SYMMETRY 158 | printf("\033[01;33m[+] Kangaroo v" RELEASE 159 | " (with symmetry [256 range edition])\n"); 160 | #else 161 | printf("\033[01;33m[+] Kangaroo v" RELEASE " [256 range edition]\n"); 162 | #endif 163 | std::cout << "\r\033[01;33m[+] " << ctime(¤tTime); 164 | // Global Init 165 | Timer::Init(); 166 | rseed(Timer::getSeed32()); 167 | 168 | // Init SecpK1 169 | Secp256K1 *secp = new Secp256K1(); 170 | secp->Init(); 171 | 172 | int a = 1; 173 | nbCPUThread = Timer::getCoreNumber(); 174 | 175 | while (a < argc) { 176 | if (strcmp(argv[a], "-t") == 0) { 177 | CHECKARG("-t", 1); 178 | nbCPUThread = getInt("nbCPUThread", argv[a]); 179 | a++; 180 | } else if (strcmp(argv[a], "-d") == 0) { 181 | CHECKARG("-d", 1); 182 | dp = getInt("dpSize", argv[a]); 183 | a++; 184 | } else if (strcmp(argv[a], "-h") == 0) { 185 | printUsage(); 186 | } else if (strcmp(argv[a], "-l") == 0) { 187 | #ifdef WITHGPU 188 | GPUEngine::PrintCudaInfo(); 189 | #else 190 | printf("GPU code not compiled, use -DWITHGPU when compiling.\n"); 191 | #endif 192 | exit(0); 193 | 194 | } else if (strcmp(argv[a], "-w") == 0) { 195 | CHECKARG("-w", 1); 196 | workFile = string(argv[a]); 197 | a++; 198 | } else if (strcmp(argv[a], "-i") == 0) { 199 | CHECKARG("-i", 1); 200 | iWorkFile = string(argv[a]); 201 | a++; 202 | } else if (strcmp(argv[a], "-wm") == 0) { 203 | CHECKARG("-wm", 1); 204 | merge1 = string(argv[a]); 205 | CHECKARG("-wm", 2); 206 | merge2 = string(argv[a]); 207 | a++; 208 | if (a < argc) { 209 | // classic merge 210 | mergeDest = string(argv[a]); 211 | a++; 212 | } 213 | } else if (strcmp(argv[a], "-wmdir") == 0) { 214 | CHECKARG("-wmdir", 1); 215 | mergeDir = string(argv[a]); 216 | CHECKARG("-wmdir", 2); 217 | mergeDest = string(argv[a]); 218 | a++; 219 | } else if (strcmp(argv[a], "-wcheck") == 0) { 220 | CHECKARG("-wcheck", 1); 221 | checkWorkFile = string(argv[a]); 222 | a++; 223 | } else if (strcmp(argv[a], "-winfo") == 0) { 224 | CHECKARG("-winfo", 1); 225 | infoFile = string(argv[a]); 226 | a++; 227 | } else if (strcmp(argv[a], "-o") == 0) { 228 | CHECKARG("-o", 1); 229 | outputFile = string(argv[a]); 230 | a++; 231 | } else if (strcmp(argv[a], "-wi") == 0) { 232 | CHECKARG("-wi", 1); 233 | savePeriod = getInt("savePeriod", argv[a]); 234 | a++; 235 | } else if (strcmp(argv[a], "-wt") == 0) { 236 | CHECKARG("-wt", 1); 237 | wtimeout = getInt("timeout", argv[a]); 238 | a++; 239 | } else if (strcmp(argv[a], "-nt") == 0) { 240 | CHECKARG("-nt", 1); 241 | ntimeout = getInt("timeout", argv[a]); 242 | a++; 243 | } else if (strcmp(argv[a], "-m") == 0) { 244 | CHECKARG("-m", 1); 245 | maxStep = getDouble("maxStep", argv[a]); 246 | a++; 247 | } else if (strcmp(argv[a], "-ws") == 0) { 248 | a++; 249 | saveKangaroo = true; 250 | } else if (strcmp(argv[a], "-wss") == 0) { 251 | a++; 252 | saveKangarooByServer = true; 253 | } else if (strcmp(argv[a], "-wsplit") == 0) { 254 | a++; 255 | splitWorkFile = true; 256 | } else if (strcmp(argv[a], "-wpartcreate") == 0) { 257 | CHECKARG("-wpartcreate", 1); 258 | workFile = string(argv[a]); 259 | Kangaroo::CreateEmptyPartWork(workFile); 260 | exit(0); 261 | } else if (strcmp(argv[a], "-s") == 0) { 262 | if (serverIP != "") { 263 | printf("-s and -c are incompatible\n"); 264 | exit(-1); 265 | } 266 | a++; 267 | serverMode = true; 268 | } else if (strcmp(argv[a], "-c") == 0) { 269 | CHECKARG("-c", 1); 270 | if (serverMode) { 271 | printf("-s and -c are incompatible\n"); 272 | exit(-1); 273 | } 274 | serverIP = string(argv[a]); 275 | a++; 276 | } else if (strcmp(argv[a], "-sp") == 0) { 277 | CHECKARG("-sp", 1); 278 | port = getInt("serverPort", argv[a]); 279 | a++; 280 | } else if (strcmp(argv[a], "-gpu") == 0) { 281 | gpuEnable = true; 282 | a++; 283 | } else if (strcmp(argv[a], "-gpuId") == 0) { 284 | CHECKARG("-gpuId", 1); 285 | getInts("gpuId", gpuId, string(argv[a]), ','); 286 | a++; 287 | } else if (strcmp(argv[a], "-g") == 0) { 288 | CHECKARG("-g", 1); 289 | getInts("gridSize", gridSize, string(argv[a]), ','); 290 | a++; 291 | } else if (strcmp(argv[a], "-v") == 0) { 292 | ::exit(0); 293 | } else if (strcmp(argv[a], "-check") == 0) { 294 | checkFlag = true; 295 | a++; 296 | } else if (a == argc - 1) { 297 | configFile = string(argv[a]); 298 | a++; 299 | } else { 300 | printf("Unexpected %s argument\n", argv[a]); 301 | exit(-1); 302 | } 303 | } 304 | 305 | if (gridSize.size() == 0) { 306 | for (int i = 0; i < gpuId.size(); i++) { 307 | gridSize.push_back(0); 308 | gridSize.push_back(0); 309 | } 310 | } else if (gridSize.size() != gpuId.size() * 2) { 311 | printf("Invalid gridSize or gpuId argument, must have coherent size\n"); 312 | exit(-1); 313 | } 314 | 315 | Kangaroo *v = 316 | new Kangaroo(secp, dp, gpuEnable, workFile, iWorkFile, savePeriod, 317 | saveKangaroo, saveKangarooByServer, maxStep, wtimeout, port, 318 | ntimeout, serverIP, outputFile, splitWorkFile); 319 | if (checkFlag) { 320 | v->Check(gpuId, gridSize); 321 | exit(0); 322 | } else { 323 | if (checkWorkFile.length() > 0) { 324 | v->CheckWorkFile(nbCPUThread, checkWorkFile); 325 | exit(0); 326 | } 327 | if (infoFile.length() > 0) { 328 | v->WorkInfo(infoFile); 329 | exit(0); 330 | } else if (mergeDir.length() > 0) { 331 | v->MergeDir(mergeDir, mergeDest); 332 | exit(0); 333 | } else if (merge1.length() > 0) { 334 | v->MergeWork(merge1, merge2, mergeDest); 335 | exit(0); 336 | } 337 | if (iWorkFile.length() > 0) { 338 | if (!v->LoadWork(iWorkFile)) exit(-1); 339 | } else if (configFile.length() > 0) { 340 | if (!v->ParseConfigFile(configFile)) exit(-1); 341 | } else { 342 | if (serverIP.length() == 0) { 343 | ::printf("No input file to process\n"); 344 | exit(-1); 345 | } 346 | } 347 | if (serverMode) 348 | v->RunServer(); 349 | else 350 | v->Run(nbCPUThread, gpuId, gridSize); 351 | } 352 | 353 | return 0; 354 | } 355 | -------------------------------------------------------------------------------- /puzzle32.txt: -------------------------------------------------------------------------------- 1 | #130 ( 1Fo65aKq8s8iquMt6weF1rku1moWVEd5Ua ) 2 | 200000000000000000000000000000000 3 | 3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 4 | 03633CBE3EC02B9401C5EFFA144C5B4D22F87940259634858FC7E59B1C09937852 5 | 6 | #135 ( 16RGFo6hjq9ym6Pj7N5H7L1NR1rVPJyw2v ) 7 | 4000000000000000000000000000000000 8 | 7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 9 | 02145D2611C823A396EF6712CE0F712F09B9B4F3135E3E0AA3230FB9B6D08D1E16 10 | 11 | #140 ( 1QKBaU6WAeycb3DbKbLBkX7vJiaS8r42Xo ) 12 | 80000000000000000000000000000000000 13 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 14 | 031F6A332D3C5C4F2DE2378C012F429CD109BA07D69690C6C701B6BB87860D6640 15 | 16 | #145 ( 19GpszRNUej5yYqxXoLnbZWKew3KdVLkXg ) 17 | 1000000000000000000000000000000000000 18 | 1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 19 | 03AFDDA497369E219A2C1C369954A930E4D3740968E5E4352475BCFFCE3140DAE5 20 | 21 | #150 ( 1MUJSJYtGPVGkBCTqGspnxyHahpt5Te8jy ) 22 | 20000000000000000000000000000000000000 23 | 3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 24 | 03137807790EA7DC6E97901C2BC87411F45ED74A5629315C4E4B03A0A102250C49 25 | 26 | #155 ( 1AoeP37TmHdFh8uN72fu9AqgtLrUwcv2wJ ) 27 | 400000000000000000000000000000000000000 28 | 7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 29 | 035CD1854CAE45391CA4EC428CC7E6C7D9984424B954209A8EEA197B9E364C05F6 30 | 31 | #160 ( 1NBC8uXJy1GiJ6drkiZa1WuKn51ps7EPTv ) 32 | 8000000000000000000000000000000000000000 33 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 34 | 02E0A8B039282FAF6FE0FD769CFBC4B6B4CF8758BA68220EAC420E32B91DDFA673 --------------------------------------------------------------------------------