packages feed

ethereum-client-haskell-0.0.1: fastNonceFinder/nonceFinder.c

#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#include "sha3.h"

#define NUMTHREADS 8

pthread_mutex_t     mutex = PTHREAD_MUTEX_INITIALIZER;

uint8_t savedNonce[32];
volatile bool nonceFound;

void saveNonce(uint8_t *val) {

  pthread_mutex_lock(&mutex);

  if (nonceFound) return; //Too late, you've been beaten to it

  memcpy(savedNonce, val, 32);

  nonceFound=true;

  pthread_mutex_unlock(&mutex);

}

struct ThreadData {
  int thread_num;
  uint8_t data[32];
  uint8_t threshold[32];
};

void getHash(uint8_t *in, uint8_t *out) {
  struct sha3_ctx ctx;
  sha3_init(&ctx, 256);
  sha3_update(&ctx, in, 64);
  sha3_finalize(&ctx, out);
}

int compare256(uint8_t first[32], uint8_t second[32]) {
  int i;
  for(i = 0; i < 32; i++) {
    if (first[i] < second[i]) return -1;
    else if (first[i] > second[i]) return 1;
  }
  return 0;
}

void increment256(uint8_t val[32]) {
  int i;
  for(i=31; i >= 0; i--) {
    val[i]++;
    if (val[i] != 0) return;
  }
}

void print256(uint8_t val[32]) {
  int i;
  for(i = 0; i < 32; i++)
    printf("%02x", val[i]);
  printf("\n");
}

void *calculateHashes(void *x) {
  uint8_t dataAndNonce[64] = {0};
  uint8_t out[32];

  struct ThreadData *threadData = (struct ThreadData *) x;

  printf("%d, #### starting thread\n", threadData->thread_num);
  

  memcpy(dataAndNonce, threadData->data, 32);

  uint64_t i;


  *(dataAndNonce + 32) = threadData->thread_num;
  while(true){
    //No mutex needed, because this is just a bool, it is only flipped to true in one place, and 
    //even if I read while writing, the worst case is that I calculate one extra sha hash.
    if (nonceFound) return NULL;
    increment256(dataAndNonce+32);
    getHash(dataAndNonce, out);
    if (compare256(out, threadData->threshold) == -1) {
      printf("data: ");
      print256(dataAndNonce);
      printf("nonce: ");
      print256(dataAndNonce+32);
      printf("out: ");
      print256(out);
      printf("done\n");
      saveNonce(dataAndNonce+32);
      return NULL;
    }
  }

  printf("shouldn't be here\n");

  exit(1);
}

int findNonce(uint8_t data[32], uint8_t threshold[32], uint8_t *out) {
  pthread_t inc_x_thread[NUMTHREADS];
  struct ThreadData threadData[NUMTHREADS];

  printf("data:      ");
  print256(data);
  printf("threshold: ");
  print256(threshold);

  int thread_num;

  int i;

  nonceFound=false;

  for(thread_num = 0; thread_num < NUMTHREADS-1; thread_num++) {
    
    memcpy(threadData[thread_num].threshold, threshold, 32);
    memcpy(threadData[thread_num].data, data, 32);
    threadData[thread_num].thread_num = thread_num;

    if(pthread_create(&inc_x_thread[thread_num], NULL, calculateHashes, (threadData+thread_num))) {
      fprintf(stderr, "Error creating thread\n");
      return 1;
    }
  }

  for(thread_num = 0; thread_num < NUMTHREADS-1; thread_num++) {
    if(pthread_join(inc_x_thread[thread_num], NULL)) {
      fprintf(stderr, "Error joining thread\n");
      return 2;
    }
  }

  assert(nonceFound);

  printf("savedNonce: ");
  print256(savedNonce);

  memcpy(out, savedNonce, 32);

  return 0;
  
}