int main(int argc, char **argv) { int i; if(argc < 3) { printf("Usage: ./mine <node url> [<plot dir> <plot dir> ..]\n"); exit(-1); } #ifdef SOLO // Reading passphrase from file int pf = open( "passphrases.txt", O_RDONLY ); if( pf < 0 ) { printf("For solo mining: could not find file passphrases.txt\nThis file should contain the passphrase used to create the plotfiles\n"); exit(-1); } int bytes = read( pf, passphrase, 2000 ); // Replace spaces with + for( i=0; i<bytes; i++ ) { if( passphrase[i] == ' ' ) passphrase[i] = '+'; // end on newline if( passphrase[i] == '\n' || passphrase[i] == '\r') passphrase[i] = 0; } passphrase[bytes] = 0; #endif // Check if all directories exist: struct stat d = {0}; for(i = 2; i < argc; i++) { if ( stat( argv[i], &d) ) { printf( "Plot directory %s does not exist\n", argv[i] ); exit(-1); } else { if( !(d.st_mode & S_IFDIR) ) { printf( "%s is not a directory\n", argv[i] ); exit(-1); } } } char *hostname = argv[1]; // Contains http://? strip it. if(strncmp(hostname, "http://", 7) == 0) hostname += 7; // Contains Port? Extract and strip. char *p = strstr(hostname, ":"); if(p != NULL) { p[0] = 0; p++; nodeport = atoi(p); } printf("Using %s port %i\n", hostname, nodeport); hostname_to_ip(hostname, nodeip); memset(oldSignature, 0, 33); pthread_t worker[argc]; time(&starttime); // Get startpoint: update(); // Main loop for(;;) { // Get scoop: char scoopgen[40]; memmove(scoopgen, signature, 32); char *mov = (char*)&height; scoopgen[32] = mov[7]; scoopgen[33] = mov[6]; scoopgen[34] = mov[5]; scoopgen[35] = mov[4]; scoopgen[36] = mov[3]; scoopgen[37] = mov[2]; scoopgen[38] = mov[1]; scoopgen[39] = mov[0]; shabal_context x; shabal_init(&x, 256); shabal(&x, scoopgen, 40); char xcache[32]; shabal_close(&x, 0, 0, xcache); scoop = (((unsigned char)xcache[31]) + 256 * (unsigned char)xcache[30]) % HASH_CAP; // New block: reset stats best = bestn = deadline = bytesRead = 0; #ifdef SHARE_POOL sharefill = 0; #endif for(i = 2; i < argc; i++) { if(pthread_create(&worker[i], NULL, work_i, argv[i])) { printf("\nError creating thread. Out of memory? Try lower stagger size\n"); exit(-1); } } #ifdef SHARE_POOL // Collect threads back in for dev's pool: for(i = 2; i < argc; i++) pthread_join(worker[i], NULL); if(sharefill > 0) { char *f1 = (char*) malloc(SHARECACHE * 100); char *f2 = (char*) malloc(SHARECACHE * 100); int used = 0; for(i = 0; i<sharefill; i++) used += sprintf(&f1[used], "%llu:%llu\n", sharekey[i], sharenonce[i]); int ilen = 1, red = used; while(red > 10) { ilen++; red /= 10; } int db = sprintf(f2, "POST /pool/submitWork HTTP/1.0\r\nHost: %s:%i\r\nContent-Type: text/plain;charset=UTF-8\r\nContent-Length: %i\r\n\r\n{\"%s\", %u}", nodeip, nodeport, used + 6 + ilen , f1, used); printf("\nServer response: %s\n", contactWallet(f2, db)); free(f1); free(f2); } #endif memmove(oldSignature, signature, 32); // Wait until block changes: do { update(); time_t ttime; time(&ttime); #ifdef SHARE_POOL printf("\r%llu MB read/%llu GB total/%i shares@target %llu ", (bytesRead / ( 1024 * 1024 )), (bytesRead / (256 * 1024)), sharefill, targetdeadline); #else if(deadline == 0) printf("\r%llu MB read/%llu GB total/no low enough deadline yet", (bytesRead / ( 1024 * 1024 )), (bytesRead / (256 * 1024))); else printf("\r%llu MB read/%llu GB total/deadline %llus (%llis left)", (bytesRead / ( 1024 * 1024 )), (bytesRead / (256 * 1024)), deadline, (long long)deadline + (unsigned int)starttime - (unsigned int)ttime); #endif fflush(stdout); struct timespec wait; // Query faster when solo mining #ifdef SOLO wait.tv_sec = 1; #else wait.tv_sec = 5; #endif wait.tv_nsec = 0; nanosleep(&wait, NULL); } while(memcmp(signature, oldSignature, 32) == 0); // Wait until signature changed printf("\nNew block %llu, basetarget %llu \n", height, baseTarget); fflush(stdout); // Remember starttime time(&starttime); #ifndef SHARE_POOL // Tell all threads to stop: stopThreads = 1; for(i = 2; i < argc; i++) pthread_join(worker[i], NULL); stopThreads = 0; #endif } }
/* see sph_shabal.h */ void sph_shabal512_init(void *cc) { shabal_init(cc, 512); }
void procscoop(unsigned long long nonce, int n, char *data, unsigned long long account_id) { char *cache; char sig[32 + 64]; cache = data; int v; memmove(sig, signature, 32); for(v=0; v<n; v++) { memmove(&sig[32], cache, 64); shabal_context x; shabal_init(&x, 256); shabal(&x, sig, 64 + 32); char res[32]; shabal_close(&x, 0, 0, res); unsigned long long *wertung = (unsigned long long*)res; // Sharepool: Submit all deadlines below threshold // Uray_pool: Submit best deadline // Solo: Best deadline, but not low quality deadlines #ifdef SHARE_POOL // For sharepool just store results for later submission if(*wertung < targetdeadline * baseTarget && sharefill < SHARECACHE) { sharekey[sharefill] = account_id; sharenonce[sharefill] = nonce; sharefill++; } #else if(bestn == 0 || *wertung <= best) { best = *wertung; bestn = nonce; #ifdef SOLO if(best < baseTarget * MAXDEADLINE) { // Has to be this good before we inform the node #endif #ifdef URAY_POOL int bytes = sprintf(writebuffer, "POST /burst?requestType=submitNonce&accountId=%llu&nonce=%llu HTTP/1.0\r\nConnection: close\r\n\r\n", account_id,bestn); #else int bytes = sprintf(writebuffer, "POST /burst?requestType=submitNonce&secretPhrase=%s&nonce=%llu HTTP/1.0\r\nConnection: close\r\n\r\n", passphrase, bestn); #endif char *buffer = contactWallet( writebuffer, bytes ); if(buffer != NULL) { char *rdeadline = strstr(buffer, "\"deadline\":"); if(rdeadline != NULL) { rdeadline += 11; char *end = strstr(rdeadline, "}"); if(end != NULL) { // Parse and check if we have a better deadline unsigned long long ndeadline = strtoull(rdeadline, 0, 10); if(ndeadline < deadline || deadline == 0) deadline = ndeadline; } } #ifdef SOLO // Deadline too high? Passphrase may be wrong. if(deadline > MAXDEADLINE) { printf("\nYour deadline is larger than it should be. Check if you put the correct passphrase to passphrases.txt.\n"); fflush(stdout); } #endif } #ifdef SOLO } #endif } #endif nonce++; cache += 64; } }
/* see sph_shabal.h */ void sph_shabal384_init(void *cc) { shabal_init(cc, 384); }
/* see sph_shabal.h */ void sph_shabal256_init(void *cc) { shabal_init(cc, 256); }
/* see sph_shabal.h */ void sph_shabal224_init(void *cc) { shabal_init(cc, 224); }
/* see sph_shabal.h */ void sph_shabal192_init(void *cc) { shabal_init(cc, 192); }
static void shabal_close(void *cc, unsigned ub, unsigned n, void *dst, unsigned size_words) { sph_shabal_context *sc; unsigned char *buf; size_t ptr; int i; unsigned z; union { unsigned char tmp_out[64]; sph_u32 dummy; } u; size_t out_len; DECL_STATE sc = cc; buf = sc->buf; ptr = sc->ptr; z = 0x80 >> n; buf[ptr] = ((ub & -z) | z) & 0xFF; memset(buf + ptr + 1, 0, (sizeof sc->buf) - (ptr + 1)); READ_STATE(sc); DECODE_BLOCK; INPUT_BLOCK_ADD; XOR_W; APPLY_P; for (i = 0; i < 3; i ++) { SWAP_BC; XOR_W; APPLY_P; } /* * We just use our local variables; no need to go through * the state structure. In order to share some code, we * emit the relevant words into a temporary buffer, which * we finally copy into the destination array. */ switch (size_words) { case 16: sph_enc32le_aligned(u.tmp_out + 0, B0); sph_enc32le_aligned(u.tmp_out + 4, B1); sph_enc32le_aligned(u.tmp_out + 8, B2); sph_enc32le_aligned(u.tmp_out + 12, B3); /* fall through */ case 12: sph_enc32le_aligned(u.tmp_out + 16, B4); sph_enc32le_aligned(u.tmp_out + 20, B5); sph_enc32le_aligned(u.tmp_out + 24, B6); sph_enc32le_aligned(u.tmp_out + 28, B7); /* fall through */ case 8: sph_enc32le_aligned(u.tmp_out + 32, B8); /* fall through */ case 7: sph_enc32le_aligned(u.tmp_out + 36, B9); /* fall through */ case 6: sph_enc32le_aligned(u.tmp_out + 40, BA); sph_enc32le_aligned(u.tmp_out + 44, BB); sph_enc32le_aligned(u.tmp_out + 48, BC); sph_enc32le_aligned(u.tmp_out + 52, BD); sph_enc32le_aligned(u.tmp_out + 56, BE); sph_enc32le_aligned(u.tmp_out + 60, BF); break; default: return; } out_len = size_words << 2; memcpy(dst, u.tmp_out + (sizeof u.tmp_out) - out_len, out_len); shabal_init(sc, size_words << 5); }