diff --git a/genesis.c b/genesis.c index bbe3261..f683249 100644 --- a/genesis.c +++ b/genesis.c @@ -1,377 +1,2 @@ -// Copyright "Remember remember the 5th of November" 2013 - -#include -#include -#include -#include -#include -#include -#include -#include - -//Copied from Bitcoin source -static const uint64_t COIN = 100000000; - -static const uint32_t OP_CHECKSIG = 172; // This is expressed as 0xAC - -typedef struct { - /* Hash of Tx */ - uint8_t merkleHash[32]; - - /* Tx serialization before hashing */ - uint8_t *serializedData; - - /* Tx version */ - uint32_t version; - - /* Input */ - uint8_t numInputs; // Program assumes one input - uint8_t prevOutput[32]; - uint32_t prevoutIndex; - uint8_t *scriptSig; - uint32_t sequence; - - /* Output */ - uint8_t numOutputs; // Program assumes one output - uint64_t outValue; - uint8_t *pubkeyScript; - - /* Final */ - uint32_t locktime; -} Transaction; - -// Got this off the internet. Am not sure if it can fail in some circumstances -void byteswap(uint8_t *buf, int length) -{ - int i; - uint8_t temp; - - for(i = 0; i < length / 2; i++) - { - temp = buf[i]; - buf[i] = buf[length - i - 1]; - buf[length - i - 1] = temp; - } -} - -// Following two functions are borrowed from cgminer. -char *bin2hex(const unsigned char *p, size_t len) -{ - char *s = malloc((len * 2) + 1); - unsigned int i; - - if (!s) - return NULL; - - for (i = 0; i < len; i++) - sprintf(s + (i * 2), "%02x", (unsigned int) p[i]); - - return s; -} - -size_t hex2bin(unsigned char *p, const char *hexstr, size_t len) -{ - int ret = 0; - size_t retlen = len; - - while (*hexstr && len) { - char hex_byte[4]; - unsigned int v; - - if (!hexstr[1]) { - return ret; - } - - memset(hex_byte, 0, 4); - hex_byte[0] = hexstr[0]; - hex_byte[1] = hexstr[1]; - - if (sscanf(hex_byte, "%x", &v) != 1) { - return ret; - } - - *p = (unsigned char) v; - - p++; - hexstr += 2; - len--; - } - - if (len == 0 && *hexstr == 0) - ret = retlen; - - return ret; -} - -Transaction *InitTransaction() -{ - Transaction *transaction; - - transaction = calloc(1, sizeof(*transaction)); - if(!transaction) - { - return NULL; - } - - // Set some initial data that will remain constant throughout the program - transaction->version = 1; - transaction->numInputs = 1; - transaction->numOutputs = 1; - transaction->locktime = 0; - transaction->prevoutIndex = 0xFFFFFFFF; - transaction->sequence = 0xFFFFFFFF; - transaction->outValue = 50*COIN; - - // We initialize the previous output to 0 as there is none - memset(transaction->prevOutput, 0, 32); - - return transaction; -} - -int main(int argc, char *argv[]) -{ - Transaction *transaction; - unsigned char hash1[32], hash2[32]; - char timestamp[255], pubkey[132]; - uint32_t timestamp_len = 0, scriptSig_len = 0, pubkey_len = 0, pubkeyScript_len = 0; - uint32_t nBits = 0; - uint32_t startNonce = 0; - uint32_t unixtime = 0; - - if((argc-1) < 3) - { - fprintf(stderr, "Usage: %s [options] \"\" \n", argv[0]); - return 0; - } - - pubkey_len = strlen(argv[1]) / 2; // One byte is represented as two hex characters, thus we divide by two to get real length. - timestamp_len = strlen(argv[2]); - - if(pubkey_len != 65) - { - fprintf(stderr, "Invalid public key length! %s\n", argv[1]); - return 1; - } - - if(timestamp_len <= 0) - { - fprintf(stderr, "Size of timestamp is 0!\n"); - return 1; - } - if (timestamp_len > 91) - { - fprintf(stderr, "Size of timestamp exceeds maximum length of 91 characters!\n"); - return 1; - } - - transaction = InitTransaction(); - if(!transaction) - { - fprintf(stderr, "Could not allocate memory! Exiting...\n"); - return 2; - } - - strncpy(pubkey, argv[1], sizeof(pubkey)); - strncpy(timestamp, argv[2], sizeof(timestamp)); - sscanf(argv[3], "%lu", (long unsigned int *)&nBits); - char *endptr = NULL; - if (argc > 4) - { - startNonce = strtoul(argv[4], &endptr, 0); - if (!endptr) - { - fprintf(stderr, "Invalid start nonce: %s\n", argv[4]); - return 1; - } - } - if (argc > 5) - { - unixtime = strtoul(argv[5], &endptr, 0); - if (!endptr) - { - fprintf(stderr, "Invalid unix time: %s\n", argv[5]); - return 1; - } - } - printf("nBits: 0x%x\nstartNonce: %u\nunixtime: %u\n", nBits, startNonce, unixtime); - - pubkey_len = strlen(pubkey) >> 1; - scriptSig_len = timestamp_len; - - // Encode pubkey to binary and prepend pubkey size, then append the OP_CHECKSIG byte - transaction->pubkeyScript = malloc((pubkey_len+2)*sizeof(uint8_t)); - pubkeyScript_len = hex2bin(transaction->pubkeyScript+1, pubkey, pubkey_len); // No error checking, yeah. - transaction->pubkeyScript[0] = 0x41; // A public key is 32 bytes X coordinate, 32 bytes Y coordinate and one byte 0x04, so 65 bytes i.e 0x41 in Hex. - pubkeyScript_len+=1; - transaction->pubkeyScript[pubkeyScript_len++] = OP_CHECKSIG; - - // Encode timestamp to binary - transaction->scriptSig = malloc(scriptSig_len*sizeof(uint8_t)); - uint32_t scriptSig_pos = 0; - - // This is basically how I believe the size of the nBits is calculated - if(nBits <= 255) - { - transaction->scriptSig[scriptSig_pos++] = 0x01; - transaction->scriptSig[scriptSig_pos++] = (uint8_t)nBits; - } - else if(nBits <= 65535) - { - transaction->scriptSig[scriptSig_pos++] = 0x02; - memcpy(transaction->scriptSig+scriptSig_pos, &nBits, 2); - scriptSig_pos+=2; - } - else if(nBits <= 16777215) - { - transaction->scriptSig[scriptSig_pos++] = 0x03; - memcpy(transaction->scriptSig+scriptSig_pos, &nBits, 3); - scriptSig_pos+=3; - } - else //else if(nBits <= 4294967296LL) - { - transaction->scriptSig[scriptSig_pos++] = 0x04; - memcpy(transaction->scriptSig+scriptSig_pos, &nBits, 4); - scriptSig_pos+=4; - } - - // Important! In the Bitcoin code there is a statement 'CBigNum(4)' - // i've been wondering for a while what it is but - // seeing as alt-coins keep it the same, we'll do it here as well - // It should essentially mean PUSH 1 byte on the stack which in this case is 0x04 or just 4 - transaction->scriptSig[scriptSig_pos++] = 0x01; - transaction->scriptSig[scriptSig_pos++] = 0x04; - if (timestamp_len > 76) { - transaction->scriptSig[scriptSig_pos++] = 0x4c; - } - - transaction->scriptSig[scriptSig_pos++] = (uint8_t)scriptSig_len; - - scriptSig_len += scriptSig_pos; - transaction->scriptSig = realloc(transaction->scriptSig, scriptSig_len*sizeof(uint8_t)); - memcpy(transaction->scriptSig+scriptSig_pos, (const unsigned char *)timestamp, timestamp_len); - - // Here we are asuming some values will have the same size - uint32_t serializedLen = - 4 // tx version - +1 // number of inputs - +32 // hash of previous output - +4 // previous output's index - +1 // 1 byte for the size of scriptSig - +scriptSig_len - +4 // size of sequence - +1 // number of outputs - +8 // 8 bytes for coin value - +1 // 1 byte to represent size of the pubkey Script - +pubkeyScript_len - +4; // 4 bytes for lock time - - // Now let's serialize the data - uint32_t serializedData_pos = 0; - transaction->serializedData = malloc(serializedLen*sizeof(uint8_t)); - memcpy(transaction->serializedData+serializedData_pos, &transaction->version, 4); - serializedData_pos += 4; - memcpy(transaction->serializedData+serializedData_pos, &transaction->numInputs, 1); - serializedData_pos += 1; - memcpy(transaction->serializedData+serializedData_pos, transaction->prevOutput, 32); - serializedData_pos += 32; - memcpy(transaction->serializedData+serializedData_pos, &transaction->prevoutIndex, 4); - serializedData_pos += 4; - memcpy(transaction->serializedData+serializedData_pos, &scriptSig_len, 1); - serializedData_pos += 1; - memcpy(transaction->serializedData+serializedData_pos, transaction->scriptSig, scriptSig_len); - serializedData_pos += scriptSig_len; - memcpy(transaction->serializedData+serializedData_pos, &transaction->sequence, 4); - serializedData_pos += 4; - memcpy(transaction->serializedData+serializedData_pos, &transaction->numOutputs, 1); - serializedData_pos += 1; - memcpy(transaction->serializedData+serializedData_pos, &transaction->outValue, 8); - serializedData_pos += 8; - memcpy(transaction->serializedData+serializedData_pos, &pubkeyScript_len, 1); - serializedData_pos += 1; - memcpy(transaction->serializedData+serializedData_pos, transaction->pubkeyScript, pubkeyScript_len); - serializedData_pos += pubkeyScript_len; - memcpy(transaction->serializedData+serializedData_pos, &transaction->locktime, 4); - serializedData_pos += 4; - - // Now that the data is serialized - // we hash it with SHA256 and then hash that result to get merkle hash - SHA256(transaction->serializedData, serializedLen, hash1); - SHA256(hash1, 32, hash2); - - // This copy isn't necessary imo, but here for clarity - memcpy(transaction->merkleHash, hash2, 32); - - char *merkleHash = bin2hex(transaction->merkleHash, 32); - byteswap(transaction->merkleHash, 32); - char *merkleHashSwapped = bin2hex(transaction->merkleHash, 32); - char *txScriptSig = bin2hex(transaction->scriptSig, scriptSig_len); - char *pubScriptSig = bin2hex(transaction->pubkeyScript, pubkeyScript_len); - printf("\nCoinbase: %s\n\nPubkeyScript: %s\n\nMerkle Hash: %s\nByteswapped: %s\n",txScriptSig, pubScriptSig, merkleHash, merkleHashSwapped); - - //if(generateBlock) - { - printf("Generating block...\n"); - if(!unixtime) - { - unixtime = time(NULL); - } - - unsigned char block_header[80], block_hash1[32], block_hash2[32]; - uint32_t blockversion = 1; - memcpy(block_header, &blockversion, 4); - memset(block_header+4, 0, 32); - byteswap(transaction->merkleHash, 32); // We swapped it before, so do it again now. - memcpy(block_header+36, transaction->merkleHash, 32); - memcpy(block_header+68, &unixtime, 4); - memcpy(block_header+72, &nBits, 4); - memcpy(block_header+76, &startNonce, 4); - - uint32_t *pNonce = (uint32_t *)(block_header + 76); - uint32_t *pUnixtime = (uint32_t *)(block_header + 68); - unsigned int counter, start = time(NULL); - while(1) - { - SHA256(block_header, 80, block_hash1); - SHA256(block_hash1, 32, block_hash2); - - unsigned int check = *((uint32_t *)(block_hash2 + 28)); // The hash is in little-endian, so we check the last 4 bytes. - if(check == 0) // \x00\x00\x00\x00 - { - byteswap(block_hash2, 32); - char *blockHash = bin2hex(block_hash2, 32); - printf("\nBlock found!\nHash: %s\nNonce: %u\nUnix time: %u", blockHash, startNonce, unixtime); - free(blockHash); - break; - } - - startNonce++; - counter+=1; - if(time(NULL)-start >= 1) - { - printf("\r%d Hashes/s, Nonce %u\r", counter, startNonce); - counter = 0; - start = time(NULL); - } - *pNonce = startNonce; - if(startNonce > 4294967294LL) - { - //printf("\nBlock found!\nHash: %s\nNonce: %u\nUnix time: %u", blockHash, startNonce, unixtime); - unixtime++; - *pUnixtime = unixtime; - startNonce = 0; - } - } - } - - // Lots of cleanup - free(merkleHash); - free(merkleHashSwapped); - free(txScriptSig); - free(pubScriptSig); - free(transaction->serializedData); - free(transaction->scriptSig); - free(transaction->pubkeyScript); - free(transaction); - - return 0; -} +A for Apple +b for Ball