#include "Blockchain.h" #include "Hash.h" #include #include typedef HashSha256 HASH_HEADER; typedef HashMd5 HASH_DATA; typedef Block<1024, HASH_HEADER, HASH_DATA> BLOCK; typedef Blockchain BLOCKCHAIN; const unsigned int DIFFICULTY = 2; static inline uint32_t getCurrentTimestamp() { time_t unix_timestamp = time(nullptr); if (-1 == unix_timestamp) { return(false); } uint32_t timestamp = unix_timestamp & 0xFFFFFFFF; // should be ok for now return(timestamp); } struct MiningBlockHeader { uint32_t version; uint32_t timestamp; HASH_HEADER previousHash; HASH_DATA dataHash; uint32_t nonce; MiningBlockHeader(const BLOCK::HASH & previousBlockHash, byte * data, unsigned int size) { version = 1; timestamp = getCurrentTimestamp(); previousHash = previousBlockHash; if (data != nullptr) { dataHash.initFromData(data, size); } nonce = 0; } }; static void print_hash(unsigned char * data, unsigned int size) { for (int i = 0; i < size; ++i) { printf("%02x", (unsigned)(*(data+i))); } } static bool print_block_info(const BLOCK & block) { BLOCK::HASH H; bool success = block.computeHash(H); if (!success) { return(false); } printf("Block "); print_hash((unsigned char*)&H, BLOCK::HASH::SIZE); printf(" : \n"); printf("\t Version : %d\n", block.getHeader().getVersion()); printf("\t Timestamp : %d\n", block.getHeader().getTimestamp()); printf("\t Previous Block : "); print_hash((unsigned char*)&block.getHeader().getPreviousHash(), HASH_HEADER::SIZE); printf(" \n"); printf("\t Data Hash : "); print_hash((unsigned char*)&block.getHeader().getDataHash(), HASH_DATA::SIZE); printf(" \n"); printf("\t Nonce : %d\n", block.getHeader().getNonce()); printf("\n"); return(true); } static inline bool isHashValidForBlockchain(BLOCKCHAIN & blockchain, const BLOCK::HASH & H) { for (int i = 0; i < blockchain.getCurrentDifficulty(); ++i) { if (H[i] != 0) { return(false); } } return(true); } static bool ComputeNonce(BLOCKCHAIN & blockchain, MiningBlockHeader & parameters) { BLOCK::HASH H; H.initFromData((byte*)¶meters, sizeof(parameters)); while (!isHashValidForBlockchain(blockchain, H)) { ++parameters.nonce; if (!H.initFromData((byte*)¶meters, sizeof(parameters))) { return(false); } } return(true); } bool CreateGenesisBlock(BLOCKCHAIN & blockchain, byte * data, unsigned int size) { BLOCK::HASH empty_hash; MiningBlockHeader parameters(empty_hash, data, size); ComputeNonce(blockchain, parameters); BLOCK block; if (!blockchain.CreateGenesisBlock(parameters.version, parameters.timestamp, parameters.nonce, data, size, block)) { printf("Block creation failed !\n"); return(false); } BLOCK::HASH H; bool success = block.computeHash(H); if (!success) { return(false); } print_block_info(block); return(true); } bool CreateEmptyGenesisBlock(BLOCKCHAIN & blockchain) { byte no_data [BLOCK::SIZE]; memset(no_data, 0, BLOCK::SIZE); return(CreateGenesisBlock(blockchain, no_data, BLOCK::SIZE)); } bool AddDataToBlockChain(BLOCKCHAIN & blockchain, const BLOCK::HASH & previousBlockHash, byte * data, unsigned int size) { MiningBlockHeader parameters(previousBlockHash, data, size); ComputeNonce(blockchain, parameters); BLOCK block; if (!blockchain.CreateBlock(parameters.version, parameters.timestamp, parameters.previousHash, parameters.nonce, data, size, block)) { printf("Block creation failed !\n"); return(false); } BLOCK::HASH H; bool success = block.computeHash(H); if (!success) { return(false); } print_block_info(block); return(true); } int main(int argc, char ** argv) { BLOCKCHAIN blockchain(DIFFICULTY); // // Create Genesis Block if (!CreateEmptyGenesisBlock(blockchain)) { return(-1); } BLOCK::HASH H; const BLOCK & genesis = blockchain.getGenesisBlock(); genesis.computeHash(H); // // Create some Block byte random_data [BLOCK::SIZE]; memset(random_data, 0, BLOCK::SIZE); for (int i = 0; i < 10; ++i) { AddDataToBlockChain(blockchain, H, random_data, BLOCK::SIZE); const BLOCK & current = blockchain.getCurrentBlock(); current.computeHash(H); } return(0); }