Add sources
This commit is contained in:
4
test/CMakeLists.txt
Normal file
4
test/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
add_executable(compute_hash compute_hash.cpp Hash.cpp Hash.h)
|
||||
|
||||
target_link_libraries(compute_hash PRIVATE blockchain md5 sha1 sha256)
|
||||
1
test/Hash.cpp
Normal file
1
test/Hash.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "Hash.h"
|
||||
187
test/Hash.h
Normal file
187
test/Hash.h
Normal file
@@ -0,0 +1,187 @@
|
||||
#pragma once
|
||||
|
||||
#include "base_types.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "md5.h"
|
||||
#include "sha1.h"
|
||||
#include "sha256.h"
|
||||
}
|
||||
|
||||
template<unsigned int HASH_SIZE>
|
||||
struct HashNull
|
||||
{
|
||||
enum { SIZE = HASH_SIZE };
|
||||
|
||||
HashNull(void)
|
||||
{
|
||||
setBytes(0);
|
||||
}
|
||||
|
||||
bool initFromData(const byte * data, unsigned int size)
|
||||
{
|
||||
setBytes(0);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
HashNull<SIZE> & operator = (byte data)
|
||||
{
|
||||
setBytes(data);
|
||||
}
|
||||
|
||||
byte operator [] (unsigned int index) const
|
||||
{
|
||||
return(checksum[index]);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void setBytes(byte data)
|
||||
{
|
||||
for (int i = 0; i < SIZE; ++i)
|
||||
{
|
||||
checksum[i] = data;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
byte checksum [SIZE];
|
||||
};
|
||||
|
||||
struct HashMd5
|
||||
{
|
||||
enum { SIZE = 16 }; // 128 bits
|
||||
|
||||
HashMd5(void)
|
||||
{
|
||||
setBytes(0);
|
||||
}
|
||||
|
||||
bool initFromData(byte * data, unsigned int size)
|
||||
{
|
||||
MD5_CTX context;
|
||||
|
||||
md5_init(&context);
|
||||
md5_update(&context, data, size);
|
||||
md5_final(&context, checksum);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
HashMd5 & operator = (byte data)
|
||||
{
|
||||
setBytes(data);
|
||||
}
|
||||
|
||||
byte operator [] (unsigned int index) const
|
||||
{
|
||||
return(checksum[index]);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void setBytes(byte data)
|
||||
{
|
||||
for (int i = 0; i < SIZE; ++i)
|
||||
{
|
||||
checksum[i] = data;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
byte checksum [SIZE];
|
||||
};
|
||||
|
||||
struct HashSha1
|
||||
{
|
||||
enum { SIZE = 20 }; // 160 bits
|
||||
|
||||
HashSha1(void)
|
||||
{
|
||||
setBytes(0);
|
||||
}
|
||||
|
||||
bool initFromData(byte * data, unsigned int size)
|
||||
{
|
||||
SHA1_CTX context;
|
||||
|
||||
sha1_init(&context);
|
||||
sha1_update(&context, data, size);
|
||||
sha1_final(&context, checksum);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
HashSha1 & operator = (byte data)
|
||||
{
|
||||
setBytes(data);
|
||||
}
|
||||
|
||||
byte operator [] (unsigned int index) const
|
||||
{
|
||||
return(checksum[index]);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void setBytes(byte data)
|
||||
{
|
||||
for (int i = 0; i < SIZE; ++i)
|
||||
{
|
||||
checksum[i] = data;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
byte checksum [SIZE];
|
||||
};
|
||||
|
||||
struct HashSha256
|
||||
{
|
||||
enum { SIZE = 32 }; // 256 bits
|
||||
|
||||
HashSha256(void)
|
||||
{
|
||||
setBytes(0);
|
||||
}
|
||||
|
||||
bool initFromData(byte * data, unsigned int size)
|
||||
{
|
||||
SHA256_CTX context;
|
||||
|
||||
sha256_init(&context);
|
||||
sha256_update(&context, data, size);
|
||||
sha256_final(&context, checksum);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
HashSha256 & operator = (byte data)
|
||||
{
|
||||
setBytes(data);
|
||||
}
|
||||
|
||||
byte operator [] (unsigned int index) const
|
||||
{
|
||||
return(checksum[index]);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void setBytes(byte data)
|
||||
{
|
||||
for (int i = 0; i < SIZE; ++i)
|
||||
{
|
||||
checksum[i] = data;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
byte checksum [SIZE];
|
||||
};
|
||||
210
test/compute_hash.cpp
Normal file
210
test/compute_hash.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
#include "Blockchain.h"
|
||||
|
||||
#include "Hash.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
typedef HashSha256 HASH_HEADER;
|
||||
typedef HashMd5 HASH_DATA;
|
||||
|
||||
typedef Block<1024, HASH_HEADER, HASH_DATA> BLOCK;
|
||||
typedef Blockchain<BLOCK> 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);
|
||||
}
|
||||
Reference in New Issue
Block a user