Add sources
This commit is contained in:
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
[submodule "external/crypto-algorithms"]
|
||||
path = external/crypto-algorithms
|
||||
url = https://github.com/B-Con/crypto-algorithms
|
||||
[submodule "external/containers"]
|
||||
path = external/containers
|
||||
url = https://github.com/magestik/containers
|
||||
21
CMakeLists.txt
Normal file
21
CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
cmake_minimum_required(VERSION 3.3)
|
||||
|
||||
project(blockchain)
|
||||
|
||||
IF(NOT CMAKE_BUILD_TYPE)
|
||||
SET(CMAKE_BUILD_TYPE Debug)
|
||||
ENDIF()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
|
||||
option(ENABLE_ASAN OFF)
|
||||
|
||||
if (ENABLE_ASAN)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
endif (ENABLE_ASAN)
|
||||
|
||||
add_subdirectory(external)
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(test)
|
||||
37
external/CMakeLists.txt
vendored
Normal file
37
external/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
add_subdirectory(containers)
|
||||
|
||||
#############################################
|
||||
|
||||
# MD2
|
||||
|
||||
add_library(md2 STATIC crypto-algorithms/md2.c crypto-algorithms/md2.h)
|
||||
target_include_directories(md2 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/crypto-algorithms/)
|
||||
|
||||
add_executable(md2_test crypto-algorithms/md2_test.c)
|
||||
target_link_libraries(md2_test PRIVATE md2)
|
||||
|
||||
# MD5
|
||||
|
||||
add_library(md5 STATIC crypto-algorithms/md5.c crypto-algorithms/md5.h)
|
||||
target_include_directories(md5 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/crypto-algorithms/)
|
||||
|
||||
add_executable(md5_test crypto-algorithms/md5_test.c)
|
||||
target_link_libraries(md5_test PRIVATE md5)
|
||||
|
||||
# SHA1
|
||||
|
||||
add_library(sha1 STATIC crypto-algorithms/sha1.c crypto-algorithms/sha1.h)
|
||||
target_include_directories(sha1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/crypto-algorithms/)
|
||||
|
||||
add_executable(sha1_test crypto-algorithms/sha1_test.c)
|
||||
target_link_libraries(sha1_test PRIVATE sha1)
|
||||
|
||||
# SHA256
|
||||
|
||||
add_library(sha256 STATIC crypto-algorithms/sha256.c crypto-algorithms/sha256.h)
|
||||
target_include_directories(sha1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/crypto-algorithms/)
|
||||
|
||||
add_executable(sha256_test crypto-algorithms/sha256_test.c)
|
||||
target_link_libraries(sha256_test PRIVATE sha256)
|
||||
|
||||
1
external/containers
vendored
Submodule
1
external/containers
vendored
Submodule
Submodule external/containers added at 67fa335974
1
external/crypto-algorithms
vendored
Submodule
1
external/crypto-algorithms
vendored
Submodule
Submodule external/crypto-algorithms added at cfbde48414
35
src/Allocator.h
Normal file
35
src/Allocator.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h> // for malloc/free & realloc
|
||||
|
||||
class HeapAllocator
|
||||
{
|
||||
public:
|
||||
|
||||
HeapAllocator(void)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
~HeapAllocator(void)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
void * allocate(unsigned int size)
|
||||
{
|
||||
void * ptr = malloc(size);
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
void release(void * ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void * resize(void * ptr, unsigned int size)
|
||||
{
|
||||
ptr = realloc(ptr, size);
|
||||
return(ptr);
|
||||
}
|
||||
};
|
||||
1
src/Block.cpp
Normal file
1
src/Block.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "Block.h"
|
||||
109
src/Block.h
Normal file
109
src/Block.h
Normal file
@@ -0,0 +1,109 @@
|
||||
#pragma once
|
||||
|
||||
#include "base_types.h"
|
||||
|
||||
template<typename HashHeader, typename HashData>
|
||||
struct BlockHeader
|
||||
{
|
||||
BlockHeader(void)
|
||||
{
|
||||
version = 1;
|
||||
timestamp = 0;
|
||||
previousHash = 0;
|
||||
dataHash = 0;
|
||||
nonce = 0;
|
||||
}
|
||||
|
||||
BlockHeader(uint32_t version_, uint32_t timestamp_, const HashHeader & previousHash_, const HashData & dataHash_, uint32_t nonce_)
|
||||
{
|
||||
version = version_;
|
||||
timestamp = timestamp_;
|
||||
previousHash = previousHash_;
|
||||
dataHash = dataHash_;
|
||||
nonce = nonce_;
|
||||
}
|
||||
|
||||
uint32_t getVersion(void) const
|
||||
{
|
||||
return(version);
|
||||
}
|
||||
|
||||
uint32_t getTimestamp(void) const
|
||||
{
|
||||
return(timestamp);
|
||||
}
|
||||
|
||||
const HashHeader & getPreviousHash(void) const
|
||||
{
|
||||
return(previousHash);
|
||||
}
|
||||
|
||||
const HashData & getDataHash(void) const
|
||||
{
|
||||
return(dataHash);
|
||||
}
|
||||
|
||||
uint32_t getNonce(void) const
|
||||
{
|
||||
return(nonce);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t version;
|
||||
uint32_t timestamp;
|
||||
HashHeader previousHash;
|
||||
HashData dataHash;
|
||||
uint32_t nonce;
|
||||
};
|
||||
|
||||
template<unsigned int BLOCK_SIZE, typename HASH_HEADER, typename HASH_DATA>
|
||||
struct Block
|
||||
{
|
||||
typedef BlockHeader<HASH_HEADER, HASH_DATA> HEADER;
|
||||
typedef HASH_HEADER HASH;
|
||||
enum { SIZE = BLOCK_SIZE };
|
||||
|
||||
Block(void) : header()
|
||||
{
|
||||
for (int i = 0; i < SIZE; ++i)
|
||||
{
|
||||
data[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Block(uint32_t version, uint32_t timestamp, const HASH & previousHash, uint32_t nonce, byte * data_) : header()
|
||||
{
|
||||
for (int i = 0; i < SIZE; ++i)
|
||||
{
|
||||
data[i] = data_[i];
|
||||
}
|
||||
|
||||
HASH_DATA dataHash;
|
||||
dataHash.initFromData(data_, SIZE);
|
||||
|
||||
header = HEADER(version, timestamp, previousHash, dataHash, nonce);
|
||||
}
|
||||
|
||||
bool computeHash(HASH & output_hash) const
|
||||
{
|
||||
// it's ok to compute header hash only
|
||||
// -> the header contains the data hash
|
||||
return(output_hash.initFromData((byte*)&header, sizeof(HEADER)));
|
||||
}
|
||||
|
||||
const HEADER & getHeader(void) const
|
||||
{
|
||||
return(header);
|
||||
}
|
||||
|
||||
const byte * getData(void) const
|
||||
{
|
||||
return(data);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
HEADER header;
|
||||
byte data [SIZE];
|
||||
};
|
||||
2
src/Blockchain.cpp
Normal file
2
src/Blockchain.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "Blockchain.h"
|
||||
|
||||
176
src/Blockchain.h
Normal file
176
src/Blockchain.h
Normal file
@@ -0,0 +1,176 @@
|
||||
#pragma once
|
||||
|
||||
#include "base_types.h"
|
||||
|
||||
#include "Block.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Array.h"
|
||||
#include "Allocator.h"
|
||||
|
||||
template<typename BLOCK>
|
||||
class Blockchain
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
INITIAL_VERSION = 1,
|
||||
CURRENT_VERSION = INITIAL_VERSION,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Default Constructor
|
||||
*/
|
||||
Blockchain(void) : difficulty(0)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor with initial difficulty
|
||||
* @param difficulty_
|
||||
*/
|
||||
Blockchain(unsigned int difficulty_) : difficulty(difficulty_)
|
||||
{
|
||||
if (difficulty > BLOCK::HASH::SIZE)
|
||||
{
|
||||
difficulty = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Current Hash computation difficulty
|
||||
* @return
|
||||
*/
|
||||
inline unsigned int getCurrentDifficulty(void) const
|
||||
{
|
||||
return(difficulty);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Genesis Block
|
||||
* @return
|
||||
*/
|
||||
inline const BLOCK & getGenesisBlock(void) const
|
||||
{
|
||||
return(*blocks[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Genesis Block
|
||||
* @return
|
||||
*/
|
||||
inline const BLOCK & getCurrentBlock(void) const
|
||||
{
|
||||
return(*blocks[blocks.count()-1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create Genesis Block without data
|
||||
* @param version
|
||||
* @param timestamp
|
||||
* @param output_block
|
||||
* @return
|
||||
*/
|
||||
bool CreateGenesisBlock(uint32_t version, uint32_t timestamp, uint32_t nonce, BLOCK & output_block)
|
||||
{
|
||||
return(CreateGenesisBlock(version, timestamp, nonce, nullptr, 0, output_block));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create Genesis Block with data
|
||||
* @param version
|
||||
* @param timestamp
|
||||
* @param output_block
|
||||
* @return
|
||||
*/
|
||||
bool CreateGenesisBlock(uint32_t version, uint32_t timestamp, uint32_t nonce, byte * data, unsigned int dataSize, BLOCK & output_block)
|
||||
{
|
||||
if (version != CURRENT_VERSION)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
typename BLOCK::HASH empty_hash;
|
||||
|
||||
return(CreateBlockInternal(version, timestamp, empty_hash, nonce, data, dataSize, output_block));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create Block
|
||||
* @param version
|
||||
* @param timestamp
|
||||
* @param previousHash
|
||||
* @param nonce
|
||||
* @param data
|
||||
* @param dataSize
|
||||
* @param output_block
|
||||
* @return
|
||||
*/
|
||||
bool CreateBlock(uint32_t version, uint32_t timestamp, const typename BLOCK::HASH & previousHash, uint32_t nonce, byte * data, unsigned int dataSize, BLOCK & output_block)
|
||||
{
|
||||
if (version != CURRENT_VERSION)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
if (data == nullptr || dataSize == 0 || dataSize > BLOCK::SIZE)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
return(CreateBlockInternal(version, timestamp, previousHash, nonce, data, dataSize, output_block));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief Create Block without checking parameters
|
||||
* @param version
|
||||
* @param timestamp
|
||||
* @param previousHash
|
||||
* @param nonce
|
||||
* @param data
|
||||
* @param dataSize
|
||||
* @param output_block
|
||||
* @return
|
||||
*/
|
||||
bool CreateBlockInternal(uint32_t version, uint32_t timestamp, const typename BLOCK::HASH & previousHash, uint32_t nonce, byte * data, unsigned int dataSize, BLOCK & output_block)
|
||||
{
|
||||
byte blockData [BLOCK::SIZE];
|
||||
memset(blockData, 0, BLOCK::SIZE);
|
||||
|
||||
if (nullptr != data)
|
||||
{
|
||||
memcpy(blockData, data, dataSize);
|
||||
}
|
||||
|
||||
BLOCK newBlock(version, timestamp, previousHash, nonce, blockData);
|
||||
|
||||
typename BLOCK::HASH H;
|
||||
newBlock.computeHash(H);
|
||||
|
||||
for (int i = 0; i < difficulty; ++i)
|
||||
{
|
||||
if (H[i] != 0)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
output_block = newBlock;
|
||||
|
||||
blocks.add(&output_block);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
unsigned int difficulty;
|
||||
|
||||
Array<BLOCK*, HeapAllocator> blocks;
|
||||
};
|
||||
|
||||
5
src/CMakeLists.txt
Normal file
5
src/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
add_library(blockchain STATIC Block.cpp Block.h Blockchain.cpp Blockchain.h base_types.h)
|
||||
|
||||
target_include_directories(blockchain PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(blockchain PUBLIC containers)
|
||||
5
src/base_types.h
Normal file
5
src/base_types.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef uint8_t byte;
|
||||
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