【区块链】C语言编程实现三叉Merkle树

这篇具有很好参考价值的文章主要介绍了【区块链】C语言编程实现三叉Merkle树。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. Merkle树简介

【区块链】C语言编程实现三叉Merkle树,c语言,区块链,信任链,去中心化

  如上图所示,Merkle 树的叶子节点为交易序列,对每一笔交易进行 Hash(SHA 256算法) 之后,然后对得到的 Hash 节点进行拼接再次进行 Hash 运算,如此递归直到递归至根节点。

【区块链】C语言编程实现三叉Merkle树,c语言,区块链,信任链,去中心化

  如上图所示 Merkle 树的优点在于可快速验证某个区块是否存在指定交易,如要验证 H k H_k Hk是否存在于该区块中,只要将 H L 、 H I J 、 H M N O P 、 H A B C D E F G H_L、H_{IJ}、H_{MNOP}、H_{ABCDEFG} HLHIJHMNOPHABCDEFG节点得到,然后从下到上不断 Hash,最后与根节点的 Hash 值进行比较,就可以快速判断交易是否在该区块中。

2. 构建Merkle树

  1. 头文件及Merkle节点类型
# include <iostream>
# include <functional>
# include<string>
using namespace std;
typedef struct MerkleNode {
	MerkleNode* Left;
	MerkleNode* Middle;
	MerkleNode* Right;
	MerkleNode* parent;
	size_t data;
};
struct MerkleTree {
	MerkleNode* RootNode;
}root;
  1. 创建三叉merkle所需函数
/* 创建merkle树 */
MerkleNode* queue[100000];
int front = 0, rear = 0, new_rear = 0;
int n;
// 字符串加密
size_t encrypt(string strInput)
{
	hash<string> Hash;
	size_t hashVal = Hash(strInput);
	return hashVal;
}

// size_t转换为字符串
string type_convert(size_t input)
{
	string output = to_string(input);
	return output;
}

// 字符串拼接
string concat(string one, string two,string three)
{
	string output = one + two + three;
	return output;
}

// 初始化叶子节点
void init_leaf_node(MerkleNode*& node,size_t data)
{
	node = (MerkleNode*)malloc(sizeof(MerkleNode));
	node->data = encrypt(type_convert(data));
	node->Left = NULL;
	node->Middle = NULL;
	node->Right = NULL;
}

// 对最后一个节点进行拷贝
MerkleNode* copy_node(MerkleNode* node)
{
	MerkleNode* new_node = (MerkleNode*)malloc(sizeof(MerkleNode));
	new_node->Left = NULL;
	new_node->Middle = NULL;
	new_node->Right = NULL;
	new_node->data = node->data;
	return new_node;
}

// 初始化分枝节点
void init_branch_node(MerkleNode* Left, MerkleNode* Middle, MerkleNode* Right)
{
	MerkleNode* node = (MerkleNode*)malloc(sizeof(MerkleNode));
	node->Left = Left;
	node->Middle = Middle;
	node->Right = Right;
	Left->parent = node;
	Middle->parent = node;
	Right->parent = node;
	node->data = encrypt(concat(type_convert(Left->data), type_convert(Middle->data), type_convert(Right->data)));
	queue[new_rear++] = node;
}

// 根据队列中的节点生成其父节点
void create_new_layer()
{
	// 补足剩余节点
	int remainder = rear % 3;
	int res = 0;
	if (remainder != 0)
	{
		res = 3 - remainder;
		MerkleNode* node = queue[rear - 1];
		for (int i = 0; i < res; i++)
		{
			queue[rear++] = copy_node(node);
		}
	}

	int loop = (rear + res) / 3;


	for (int i = 0; i < loop; i++)
	{
		MerkleNode* Left = queue[front++];
		MerkleNode* Middle = queue[front++];
		MerkleNode* Right = queue[front++];
		init_branch_node(Left, Middle, Right);
	}
	rear = new_rear;
	new_rear = 0;
	front = 0;
}

// 创建merkle树
void create_merkle_tree(MerkleTree*& root)
{
	while (rear != 1)
	{
		create_new_layer();
	}
	root = (MerkleTree*)malloc(sizeof(MerkleTree));
	root->RootNode = queue[rear-1];
	root->RootNode->parent = NULL;
}

// 输入数据
void init_data()
{
	cout << "请输入交易序列个数:";
	cin >> n;
	cout << "请输入每一笔交易(中间以空格隔开):";
	for (int i = 0; i < n; i++)
	{
		MerkleNode* node;
		size_t data;
		cin >> data;
		init_leaf_node(node, data);
		queue[rear++] = node;
	}
}

3. 生成SPV路径

SPV路径生成代码:

/*  生成SPV路径  */ 
size_t spv_queue[100010];
MerkleNode *sequence[100010];
int seq_front = 0, seq_rear = 0;
int spv_front = 0,spv_rear = 0;
int spv_flag[100010], flag_idx = 0;

void init_all_node_sequence(MerkleNode* node)
{
	sequence[++seq_rear] = node;
	while (seq_front != seq_rear)
	{
		MerkleNode* new_node = sequence[++seq_front];
		if (new_node->Left != NULL)
		{
			sequence[++seq_rear] = new_node->Left;
		}
		if (new_node->Middle != NULL)
		{
			sequence[++seq_rear] = new_node->Middle;
		}
		if (new_node->Right != NULL)
		{
			sequence[++seq_rear] = new_node->Right;
		}
	}
	seq_front = 0;
}

void init_spv_path(int idx,MerkleTree *root)
{
	MerkleNode* head_node = root->RootNode;
	init_all_node_sequence(head_node);

	int cnt;
	if (n % 3 == 0)
	{
		cnt = 3;
	}
	else if((n + 1) % 3 == 0) {
		cnt = n + 1;
	}
	else {
		cnt = n + 2;
	}
	int seq_idx = seq_rear - (cnt - idx);
	cout << "该交易的哈希值为:" << sequence[seq_idx]->data<< endl;

	MerkleNode* node = sequence[seq_idx];

	while (node->parent)
	{
		MerkleNode* parent = node->parent;
		if (node == parent->Left)
		{
			spv_flag[flag_idx++] = 0;
			spv_queue[++spv_rear] = parent->Middle->data;
			spv_queue[++spv_rear] = parent->Right->data;
		}
		else if (node == parent->Middle)
		{
			spv_flag[flag_idx++] = 1;
			spv_queue[++spv_rear] = parent->Left->data;
			spv_queue[++spv_rear] = parent->Right->data;
		}
		else {
			spv_flag[flag_idx++] = 2;
			spv_queue[++spv_rear] = parent->Left->data;
			spv_queue[++spv_rear] = parent->Middle->data;
		}
		node = node->parent;
	}

}

void print_spv_path(int idx)
{
	cout << "交易序列号" << idx << "的SPV路径为:";
	while (spv_front != spv_rear)
	{
		cout << spv_queue[++spv_front] << " ";
	}
	cout << endl;
	spv_front = 0;
	cout << "生成交易在其兄弟节点中的位置序列为(0为Left,1为Middle,2为Right):";
	for (int i = 0; i < flag_idx; i++)
	{
		cout << spv_flag[i] << " ";
	}
}

4. 验证SPV路径

SPV路径验证代码:

/* 验证SPV路径 */
size_t root_hash, spv_path[1010], hash_val;
int spv_length;
void judge_spv_path()
{
	cout << "请输入merkle树根节点哈希值:";
	cin >> root_hash;

	cout << "请输入SPV路径长度:";
	cin >> spv_length;
	cout << "请输入SPV路径(中间用空格隔开):";
	for (int i = 0; i < spv_length; i++)
	{
		cin >> spv_path[i];
	}

	int pos_cnt, pos_sqe[100010];
	cout << "请输入交易位置序列个数:";
	cin >> pos_cnt;
	cout << "请输入交易位置序列(中间用空格隔开):";
	for (int i = 0; i < pos_cnt; i++)
	{
		cin >> pos_sqe[i];
	}

	cout << "请输入要查询的交易哈希值:";
	cin >> hash_val;

	int path_idx = 0, pos_idx = 0;
	while (path_idx != spv_length)
	{
		size_t one = spv_path[path_idx++];
		size_t two = spv_path[path_idx++];
		if (pos_sqe[pos_idx] == 0)
		{
			hash_val = encrypt(concat(type_convert(hash_val), type_convert(one), type_convert(two)));
		}
		else if (pos_sqe[pos_idx] == 1)
		{
			hash_val = encrypt(concat(type_convert(one), type_convert(hash_val), type_convert(two)));
		}
		else {
			hash_val = encrypt(concat(type_convert(one), type_convert(two), type_convert(hash_val)));
		}
		pos_idx++;
	}
	cout << "SPV计算得到的哈希值为:" << hash_val <<endl;
	cout << "头节点哈希值为:" << root_hash << endl;
	if (hash_val == root_hash)
	{
		cout << "SPV路径验证成功!!!" << endl << endl << endl;
	}
}

5. 三叉Merkle树创建、SPV生成及验证总程序

# define _CRT_SECURE_NO_DEPRECATE
# include <iostream>
# include <functional>
# include<string>
using namespace std;
typedef struct MerkleNode {
	MerkleNode* Left;
	MerkleNode* Middle;
	MerkleNode* Right;
	MerkleNode* parent;
	size_t data;
};
struct MerkleTree {
	MerkleNode* RootNode;
}root;

/* 创建merkle树 */
MerkleNode* queue[100000];
int front = 0, rear = 0, new_rear = 0;
int n;
// 字符串加密
size_t encrypt(string strInput)
{
	hash<string> Hash;
	size_t hashVal = Hash(strInput);
	return hashVal;
}

// size_t转换为字符串
string type_convert(size_t input)
{
	string output = to_string(input);
	return output;
}

// 字符串拼接
string concat(string one, string two,string three)
{
	string output = one + two + three;
	return output;
}

// 初始化叶子节点
void init_leaf_node(MerkleNode*& node,size_t data)
{
	node = (MerkleNode*)malloc(sizeof(MerkleNode));
	node->data = encrypt(type_convert(data));
	node->Left = NULL;
	node->Middle = NULL;
	node->Right = NULL;
}

// 对最后一个节点进行拷贝
MerkleNode* copy_node(MerkleNode* node)
{
	MerkleNode* new_node = (MerkleNode*)malloc(sizeof(MerkleNode));
	new_node->Left = NULL;
	new_node->Middle = NULL;
	new_node->Right = NULL;
	new_node->data = node->data;
	return new_node;
}

// 初始化分枝节点
void init_branch_node(MerkleNode* Left, MerkleNode* Middle, MerkleNode* Right)
{
	MerkleNode* node = (MerkleNode*)malloc(sizeof(MerkleNode));
	node->Left = Left;
	node->Middle = Middle;
	node->Right = Right;
	Left->parent = node;
	Middle->parent = node;
	Right->parent = node;
	node->data = encrypt(concat(type_convert(Left->data), type_convert(Middle->data), type_convert(Right->data)));
	queue[new_rear++] = node;
}

// 根据队列中的节点生成其父节点
void create_new_layer()
{
	// 补足剩余节点
	int remainder = rear % 3;
	int res = 0;
	if (remainder != 0)
	{
		res = 3 - remainder;
		MerkleNode* node = queue[rear - 1];
		for (int i = 0; i < res; i++)
		{
			queue[rear++] = copy_node(node);
		}
	}

	int loop = (rear + res) / 3;


	for (int i = 0; i < loop; i++)
	{
		MerkleNode* Left = queue[front++];
		MerkleNode* Middle = queue[front++];
		MerkleNode* Right = queue[front++];
		init_branch_node(Left, Middle, Right);
	}
	rear = new_rear;
	new_rear = 0;
	front = 0;
}

// 创建merkle树
void create_merkle_tree(MerkleTree*& root)
{
	while (rear != 1)
	{
		create_new_layer();
	}
	root = (MerkleTree*)malloc(sizeof(MerkleTree));
	root->RootNode = queue[rear-1];
	root->RootNode->parent = NULL;
}

// 输入数据
void init_data()
{
	cout << "请输入交易序列个数:";
	cin >> n;
	cout << "请输入每一笔交易(中间以空格隔开):";
	for (int i = 0; i < n; i++)
	{
		MerkleNode* node;
		size_t data;
		cin >> data;
		init_leaf_node(node, data);
		queue[rear++] = node;
	}
}



/*  生成SPV路径  */ 
size_t spv_queue[100010];
MerkleNode *sequence[100010];
int seq_front = 0, seq_rear = 0;
int spv_front = 0,spv_rear = 0;
int spv_flag[100010], flag_idx = 0;

void init_all_node_sequence(MerkleNode* node)
{
	sequence[++seq_rear] = node;
	while (seq_front != seq_rear)
	{
		MerkleNode* new_node = sequence[++seq_front];
		if (new_node->Left != NULL)
		{
			sequence[++seq_rear] = new_node->Left;
		}
		if (new_node->Middle != NULL)
		{
			sequence[++seq_rear] = new_node->Middle;
		}
		if (new_node->Right != NULL)
		{
			sequence[++seq_rear] = new_node->Right;
		}
	}
	seq_front = 0;
}

void init_spv_path(int idx,MerkleTree *root)
{
	MerkleNode* head_node = root->RootNode;
	init_all_node_sequence(head_node);

	int cnt;
	if (n % 3 == 0)
	{
		cnt = 3;
	}
	else if((n + 1) % 3 == 0) {
		cnt = n + 1;
	}
	else {
		cnt = n + 2;
	}
	int seq_idx = seq_rear - (cnt - idx);
	cout << "该交易的哈希值为:" << sequence[seq_idx]->data<< endl;

	MerkleNode* node = sequence[seq_idx];

	while (node->parent)
	{
		MerkleNode* parent = node->parent;
		if (node == parent->Left)
		{
			spv_flag[flag_idx++] = 0;
			spv_queue[++spv_rear] = parent->Middle->data;
			spv_queue[++spv_rear] = parent->Right->data;
		}
		else if (node == parent->Middle)
		{
			spv_flag[flag_idx++] = 1;
			spv_queue[++spv_rear] = parent->Left->data;
			spv_queue[++spv_rear] = parent->Right->data;
		}
		else {
			spv_flag[flag_idx++] = 2;
			spv_queue[++spv_rear] = parent->Left->data;
			spv_queue[++spv_rear] = parent->Middle->data;
		}
		node = node->parent;
	}

}

void print_spv_path(int idx)
{
	cout << "交易序列号" << idx << "的SPV路径为:";
	while (spv_front != spv_rear)
	{
		cout << spv_queue[++spv_front] << " ";
	}
	cout << endl;
	spv_front = 0;
	cout << "生成交易在其兄弟节点中的位置序列为(0为Left,1为Middle,2为Right):";
	for (int i = 0; i < flag_idx; i++)
	{
		cout << spv_flag[i] << " ";
	}
}

/* 验证SPV路径 */
size_t root_hash, spv_path[1010], hash_val;
int spv_length;
void judge_spv_path()
{
	cout << "请输入merkle树根节点哈希值:";
	cin >> root_hash;

	cout << "请输入SPV路径长度:";
	cin >> spv_length;
	cout << "请输入SPV路径(中间用空格隔开):";
	for (int i = 0; i < spv_length; i++)
	{
		cin >> spv_path[i];
	}

	int pos_cnt, pos_sqe[100010];
	cout << "请输入交易位置序列个数:";
	cin >> pos_cnt;
	cout << "请输入交易位置序列(中间用空格隔开):";
	for (int i = 0; i < pos_cnt; i++)
	{
		cin >> pos_sqe[i];
	}

	cout << "请输入要查询的交易哈希值:";
	cin >> hash_val;

	int path_idx = 0, pos_idx = 0;
	while (path_idx != spv_length)
	{
		size_t one = spv_path[path_idx++];
		size_t two = spv_path[path_idx++];
		if (pos_sqe[pos_idx] == 0)
		{
			hash_val = encrypt(concat(type_convert(hash_val), type_convert(one), type_convert(two)));
		}
		else if (pos_sqe[pos_idx] == 1)
		{
			hash_val = encrypt(concat(type_convert(one), type_convert(hash_val), type_convert(two)));
		}
		else {
			hash_val = encrypt(concat(type_convert(one), type_convert(two), type_convert(hash_val)));
		}
		pos_idx++;
	}
	cout << "SPV计算得到的哈希值为:" << hash_val <<endl;
	cout << "头节点哈希值为:" << root_hash << endl;
	if (hash_val == root_hash)
	{
		cout << "SPV路径验证成功!!!" << endl << endl << endl;
	}
}



int main()
{

	cout << "================================================  Merkle树构建部分  ===================================================" << endl << endl;
	init_data();	// 数据初始化(输入相关数据)
	// 生成 Merkle 树
	MerkleTree* root;
	create_merkle_tree(root);
	cout << "merkle树根哈希值为:" << root->RootNode->data << endl;
	cout << "merkle树构建完成!" << endl << endl << endl;

	// 生成SPV路径
	cout << "================================================  SPV路径生成部分  ===================================================" << endl << endl;
	int idx;
	cout << "请输入交易序号(i):";
	cin >> idx;
	init_spv_path(idx, root);
	print_spv_path(idx);
	cout << endl << endl << endl;

	// 验证SPV路径
	cout << "================================================  SPV路径验证部分  ===================================================" << endl << endl;
	judge_spv_path();

	return 0;
}

6. 程序运行结果

【区块链】C语言编程实现三叉Merkle树,c语言,区块链,信任链,去中心化文章来源地址https://www.toymoban.com/news/detail-850560.html

到了这里,关于【区块链】C语言编程实现三叉Merkle树的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 用C语言编程实现两个字符串数组的连接

    写一函数,将两个字符串连接。不要使用 strcat 函数。 说明: (1)连接两个字符串的函数名为:Connect; (2)将连个字符串存入两个字符串数组中,要保证第一个字符串的长度能够容纳两个字符串之和; (3)连接两个字符串主要是找到第一个字符串的结尾,然后将第二个字

    2024年02月12日
    浏览(36)
  • 【C语言】C语言编程实战:Base64编解码算法从理论到实现(附完整代码)

    🧑 作者简介 :阿里巴巴嵌入式技术专家,深耕嵌入式+人工智能领域,具备多年的嵌入式硬件产品研发管理经验。 📒 博客介绍 :分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导、简历面试辅导、技术架构设计优化、开发外包等服

    2024年03月13日
    浏览(33)
  • Ubuntu22.2下C语言编程实现,首次,最佳适应算法

    编写C语言程序,模拟实现首次/最佳/最坏适应算法(选择其中之一即可)的内存块分配和回收,要求每次分配和回收后显示出空闲分区和已分配分区的情况。假设初始状态下,可用的内存空间为640KB。 假设下列作业请求序列: (1)作业1 申请130 KB (2)作业2 申请60 KB (3)作业

    2024年02月05日
    浏览(38)
  • C语言编程实现,计算每天进步一点点一年后的效果

    本来的基数为1,如果好好学习时能力值相比前一天提高1%,当放任时相比前一天下降1%。1年(365天)后的效果相差多少呢? 原基数为1,努力一天进步1%,效果1*(1+0.01),努力两天是在前一天的基础上进步1%,结果是1*(1+0.01)*(1+0.01),一年后天天向上的力量是(1+0.01)的365次方。

    2024年02月11日
    浏览(43)
  • 函数探秘:深入理解C语言函数,实现高效模块化编程

    ✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:C语言学习 贝蒂的主页:Betty‘s blog 在数学中我们就知道了函数这个概念,而C语言同样引入了函数这个概念,那C语言的函数到底是什么样的呢? 在C语言中, 函数也叫子程序,它是一段可以

    2024年03月09日
    浏览(50)
  • C语言网络编程:实现自己的高性能网络框架

    一般生产环境中最耗时的其实是业务逻辑处理。所以,是不是可以将处理业务逻辑的代码给拆出来丢到线程池中去执行。 比如像下面这样: ​我们事先创建好一堆worker线程,主线程accepter拿到一个连接上来的套接字,就从线程池中取出一个线程将这个套接字交给它。这样,我

    2024年02月10日
    浏览(41)
  • 马上七夕到了,用各种编程语言实现10种浪漫表白方式

    在七夕节这个充满爱意的日子里,用编程语言编写一些表白代码是个非常有趣的想法。以下是使用 各种编程语言Python、Java、JavaScript、H5等编写的 10 种简单表白代码示例,以下只是抛砖引玉,还需要你用心修改,对方一定能理解你的真心。 这段代码使用 Python 的 Matplotlib 库绘

    2024年02月12日
    浏览(28)
  • FFT原理(基2DIT-FFT)及C语言编程思路及实现

    首先说明:采用的是基2时域抽取法(Decimation-In-Time FFT 简称DIT-FFT)。         FFT实际上是对DFT的一种快速实现算法,实质上就是对DFT抽取,以8点DFT为例:可以分解为两个4点DFT,在继续分解为4个两点DFT,从而缩小DFT运算量,提高运算效率。(因此首先需要理解DFT算法和它

    2023年04月10日
    浏览(28)
  • 判断字符串是否为回文的三种常用编程语言实现

    引言:回文是一种具有镜像对称性的字符串,即它从左到右读和从右到左读是相同的。回文可以在文学、语言学、数学、计算机科学等领域中得到广泛应用。在计算机科学中,判断一个字符串是否为回文是一项基本的算法挑战。在本文中,我们将介绍三种常见的编程语言中用

    2024年02月03日
    浏览(46)
  • 【C语言实现windows环境下Socket编程TCP/IP协议】

    代码是别人的,问题是我的。顺便记录一下遇见的各种问题和我的解决办法。 可能的解决方案: 1、服务端和客户端不在一个局域网,可以开热点,这样就在了。然后ipconfig查看IP地址,就ok了。至于怎么查看在不在就ping一下对方就好了。 2、一个局域网下也ping不通:看看自己

    2024年02月04日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包