包括json库的相关读取,proof-of-work算法的实现,Merkel Tree的构建,使用hash创建新块等内容,使用本地json文件模拟mempool和block chain,C++编写。
#include <iostream>
#include <fstream>
#include <string>
#include <nlohmann/json.hpp>
#include <zlib.h>
#include <openssl/sha.h>
using namespace std;
using json = nlohmann::json;
/*{"header":{
"difficulty":3,
"height":120,
"miner":"0xca4388fb6d0ee25d59c24360e49c2dd4c9d02727",
"nonce":320,
"hash":"0x000a3698e344f2549cb88537e129a37ac78e195c08006486f928cc465bcc0550",
"previous_block_header_hash":"0x000232491f11addef82c7217de3c8f03873975442192fe6e41437bd6584585c8",
"timestamp":1697413800,
"transactions_count":70,
"transactions_merkle_root":"0xdc73d314ad97973cfcebff8ae6c5f06d545156a543be949ed237f1ca9ac3f70f"},*/
/*transaction
{
" receiver ": "0 xb0d7e24e8818e78878c116e73ea6a081d1f12b7d ",
" lock_time ": 0,
" transaction_fee ": 86 ,
" amount ": 72619 ,
" sender ": "0 x3a55c9e459c0c5b744fa4839d5e833af96c503be ",
" signature ": "0 x305930130 ... f78a667 "
}*/
string sha256_my(const string str)
{
char buf[2];
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, str.c_str(), str.size());
SHA256_Final(hash, &sha256);
std::string NewString = "";
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
sprintf(buf,"%02x",hash[i]);
NewString = NewString + buf;
}
return NewString;
}
string H(string a, string b)
{
string res = "0x";
if (a < b)
{
res += sha256_my(a + b);
}
else
{
res += sha256_my(b + a);
}
return res;
}
int main()
{
/*have decompressed the gz to json*/
/* get header from blockchain.json.gz */
std::ifstream f("blockchain.json");
json blockchain = json::parse(f);
/* Load the most recent block header hash*/
json recent_block = *blockchain.rbegin();
/*part 2: use proof-of-work algorithm to produce new block*/
std::ifstream f2("mempool.json");
json mempool = json::parse(f2);
/*part2-1*/
int blockTimestamp = recent_block["header"]["timestamp"];
//int transactions_count = recent_block["header"]["transactions_count"];
const int max_txn_num = 100;
json profitableTransactions;
for(auto it = mempool.begin(); it != mempool.end(); it++) {
/*fliter*/
if((*it)["lock_time"] <= blockTimestamp) {
profitableTransactions.push_back(*it);
}
if(profitableTransactions.size() >= max_txn_num) {
break;
}
}
sort(profitableTransactions.begin(), profitableTransactions.end(), mycomp);//lexicographic order???
/*part2-2 construct the markle tree*/
/*get txn hash*/
//2-AVL? : markle tree
vector<string> txn_sha;
for(auto it = profitableTransactions.begin(); it != profitableTransactions.end(); it++) {
// serialised transaction
string serialised_txn = "";
auto one_txn = *it;
for(auto it2 = one_txn.begin(); it2 != one_txn.end(); it2++) {
one_txn += it2.value();
if(it2 != one_txn.begin())
one_txn += ",";
}
txn_sha.push_back(sha256_my(serialised_txn));
}
vector<string> MerkleTree(txn_sha);
if(MerkleTree.empty()) {
cout<<"error: MerkleTree empty"<<endl;
exit(-1);
}
while(MerkleTree.size() != 1) {
vector<string> temp;
for(int i=1;i<MerkleTree.size();i+=2) {
temp.push_back(H(MerkleTree[i-1], MerkleTree[i]));
}
if(MerkleTree.size() % 2 == 1) {
temp.push_back(H(*MerkleTree.rbegin(), ""));//take "" as 0
}
temp.swap(MerkleTree);
}
string MerkleRoot = MerkleTree[0];
//part2-3:
json new_block = recent_block;
//fill header
new_block["header"]["height"] += 1;
new_block["header"]["miner"] ="0x00132b386d939d081bffad6dbaef99e7d4618862";
new_block["header"]["nonce"] = 0;
new_block["header"]["previous_block_header_hash"] = recent_block["header"]["hash"];
new_block["header"]["timestamp"] += 10;
new_block["header"]["transactions_count"] = profitableTransactions.size();
new_block["header"]["transactions_merkle_root"] = MerkleRoot;
//fill transactions
new_block["transactions"].clear();
for(auto it = profitableTransactions.begin(); it != profitableTransactions.end(); it++) {
new_block["transactions"].push_back(*it);
}
// part2-4:Mine the block, Proof-of-Work algorithm
string str_to_hash1 = "";
str_to_hash1 += to_string(new_block["header"]["difficulty"]) + ",";
str_to_hash1 += to_string(new_block["header"]["height"]) + ",";
str_to_hash1 += new_block["header"]["miner"] + ",";
string str_to_hash2 = ",";
str_to_hash2 += new_block["header"]["previous_block_header_hash"] + ",";
str_to_hash2 += to_string(new_block["header"]["timestamp"]) + ",";
str_to_hash2 += to_string(new_block["header"]["transactions_count"]) + ",";
str_to_hash2 += new_block["header"]["transactions_merkle_root"];
for (int i = 0;; i++) {
string str = str_to_hash1 + to_string(i) + str_to_hash2;
string res = sha256_my(str);
string effective_pos = res.substr(0, new_block["header"]["difficulty"]);
if(effective_pos.find_last_not_of("0") == string::npos) {
new_block["header"]["hash"] = "0x" + res;
break;
}
if(i % 100000 == 0) {
cout<<"i"<<endl;
}
}
//part3: write back
std::ofstream o("blockchain1.json");
o << new_block;
return 0;
}
标签:txn,sha256,hash,string,以太,json,链上,区块,block
From: https://www.cnblogs.com/kazusarua/p/17790479.html