// Copyright (c) 2011, Joseph Matheney
#include <openssl/sha.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// this is the block header, it is 80 bytes long (steal this code)
typedef struct block_header {
    unsigned int    version;
    unsigned char   prev_block[32];
    unsigned char   merkle_root[32];
    unsigned int    timestamp;
    unsigned int    bits;
    unsigned int    nonce;
} block_header;


// we need a helper function to convert hex to binary, this function is unsafe and slow, but very readable (write something better)
void hex2bin(unsigned char* dest, unsigned char* src)
{
    unsigned char bin;
    int c, pos;
    char buf[3];

    pos=0;
    c=0;
    buf[2] = 0;
    while(c < strlen(src))
    {
	    // read in 2 characaters at a time
	    buf[0] = src[c++];
	    buf[1] = src[c++];
	    // convert them to a interger and recast to a char (uint8)
	    dest[pos++] = (unsigned char)strtol(buf, NULL, 16);
    }
   
}

// this function is mostly useless in a real implementation, were only using it for demonstration purposes
void hexdump(unsigned char* data, int len)
{
    int c;
   
    c=0;
    while(c < len)
    {
	    printf("%.2x", data[c++]);
    }
    printf("\n");
}

// this function swaps the byte ordering of binary data, this code is slow and bloated (write your own)
void byte_swap(unsigned char* data, int len) {
    int c;
    unsigned char tmp[len];
   
    c=0;
    while(c<len)
    {
	    tmp[c] = data[len-(c+1)];
	    c++;
    }
   
    c=0;
    while(c<len)
    {
	    data[c] = tmp[c];
	    c++;
    }
}

int main() {
    // start with a block header struct
    block_header header;
   
    // we need a place to store the checksums
    unsigned char hash1[SHA256_DIGEST_LENGTH];
    unsigned char hash2[SHA256_DIGEST_LENGTH];
   
    // you should be able to reuse these, but openssl sha256 is slow, so your probbally not going to implement this anyway
SHA256_CTX sha256_pass1, sha256_pass2;


    // we are going to supply the block header with the values from the generation block 0
    header.version =        1;
    hex2bin(header.prev_block,              "0000000000000000000000000000000000000000000000000000000000000000");
    hex2bin(header.merkle_root,             "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
    header.timestamp =      1231006505;
    header.bits =           486604799;
    header.nonce =          2083236893;
   
    // the endianess of the checksums needs to be little, this swaps them form the big endian format you normally see in block explorer
    byte_swap(header.prev_block, 32);
    byte_swap(header.merkle_root, 32);
   
    // dump out some debug data to the terminal
    printf("sizeof(block_header) = %d\n", sizeof(block_header));
    printf("Block header (in human readable hexadecimal representation): ");
    hexdump((unsigned char*)&header, sizeof(block_header));

    // Use SSL's sha256 functions, it needs to be initialized
SHA256_Init(&sha256_pass1);
// then you 'can' feed data to it in chuncks, but here were just making one pass cause the data is so small
SHA256_Update(&sha256_pass1, (unsigned char*)&header, sizeof(block_header));
// this ends the sha256 session and writes the checksum to hash1
SHA256_Final(hash1, &sha256_pass1);
   
    // to display this, we want to swap the byte order to big endian
    byte_swap(hash1, SHA256_DIGEST_LENGTH);
    printf("Useless First Pass Checksum: ");
    hexdump(hash1, SHA256_DIGEST_LENGTH);

    // but to calculate the checksum again, we need it in little endian, so swap it back
    byte_swap(hash1, SHA256_DIGEST_LENGTH);
   
//same as above
SHA256_Init(&sha256_pass2);
SHA256_Update(&sha256_pass2, hash1, SHA256_DIGEST_LENGTH);
SHA256_Final(hash2, &sha256_pass2);
   
    byte_swap(hash2, SHA256_DIGEST_LENGTH);
    printf("Target Second Pass Checksum: ");
    hexdump(hash2, SHA256_DIGEST_LENGTH);

    return 0;
}

