RapidChain选举网络_Demo

RapidChain选举网络-Demo

这两天看到了 RapidChain 系统,对它的选举网络挺感兴趣,决定复现一下

下面是它的架构图

example

假设:分片配置环节初始节点集已经建立了身份

然后通过一定的算法(论文中提到的是哈希取区间)从节点池中选取一部分构成组,再在组中选取特定节点构成更高一级的组,层层推进,最终形成一个个分片委员会

接下来我将对这块内容对于 恶意节点的抵抗模拟 进行简单复现,由于节点数不足,哈希取区间的算法被替代为随机数

RapidChain_with_log

这里我将分布放出完整代码并作一定的解释

代码仍然是用 rust 写的,同时引入了包 rand(0.8.5),终端输入以下内容

1
cargo add rand

假定7的倍数为恶意节点,把45个节点5个一组进行分组成为一个次级委员会

9个次级委员会,3个一组,每个次级委员会选出一个代表,形成正式委员会

首先导入库

1
2
3
4
use rand::seq::SliceRandom;
use rand::{thread_rng, Rng};
use std::fs::File;
use std::io::Write;

接下来是主函数,首先 创建日志文件格式化信息

1
2
3
4
5
6
7
// 创建日志文件
let mut log_file = File::create("log.txt").unwrap();
writeln!(&mut log_file, "循环次数: 50").unwrap();

// 格式化统计信息
let mut sec_tol: Vec<u32> = vec![0; 5];
let mut ird_tol: Vec<u32> = vec![0; 4];

接下来是一个大循环,之后的大部分代码都写在循环中。这也是这次实验的关键代码,下面的代码可以通过函数进行替换,这里放出初始部分,可以更直观展示进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// 循环50次
for _i in 1..=50 {
//writeln!(&mut log_file, "第{}次测试", i).unwrap();

let mut rng = thread_rng();
let mut numbers: Vec<u32> = (1..=45).collect();

// 随机打乱数组
numbers.shuffle(&mut rng);

// 取前5个数字作为一组
let _group: Vec<u32> = numbers.iter().take(45).cloned().collect();
//println!("随机分配的45个数字为: {:?}", group);
//writeln!(&mut log_file, "随机分配的45个数字为: {:?}", group).unwrap();

// 将数组分为每组5个元素的子数组,并对每组进行排序
let groups: Vec<Vec<u32>> = numbers
.chunks(5)
.map(|chunk| {
let mut group = chunk.to_vec();
group.sort();
group
})
.collect();

// 打印每组并统计恶意节点的出现次数
let mut total_malicious_count = 0;
for (_i, group) in groups.iter().enumerate() {
let mut malicious_count = 0;
for &num in group.iter() {
if num % 7 == 0 {
malicious_count += 1;
}
}
total_malicious_count += malicious_count;
/*
println!("第{}组: {:?}, 恶意节点数: {}",i + 1,group,malicious_count);

writeln!(&mut log_file,"第{}组: {:?}, 恶意节点数: {}",i + 1,group,
malicious_count).unwrap();
*/
}
//println!("总共检测到 {} 个恶意节点", total_malicious_count);
//writeln!(&mut log_file, "总共检测到 {} 个恶意节点", total_malicious_count).unwrap();

//println!();

let mut index = 0;
let mut sec_vec = vec![0; 9];
for (_i, group) in groups.iter().enumerate() {
if sec_vec[index] == 0 {
let random_index = rng.gen_range(0..4);
sec_vec[index] = group[random_index];
//println!("第{}个位置为{}", index + 1, group[random_index]);
//writeln!(&mut log_file, "第{}个位置为{}", index + 1, group[random_index]).unwrap();
index += 1;
}
}
//println!();

// 打印每组并统计恶意节点的出现次数
total_malicious_count = 0;
for (_i, num) in sec_vec.iter().enumerate() {
let mut malicious_count = 0;
if num % 7 == 0 {
malicious_count += 1;
}
total_malicious_count += malicious_count;
//println!("第{}组: {:?}, 恶意节点数: {}", i + 1, num, malicious_count);
//writeln!(&mut log_file, "第{}组: {:?}, 恶意节点数: {}", i + 1, num, malicious_count).unwrap();
}
//println!("总共检测到 {} 个恶意节点", total_malicious_count);
//writeln!(&mut log_file, "总共检测到 {} 个恶意节点", total_malicious_count).unwrap();
match total_malicious_count {
0 => sec_tol[0] += 1,
1 => sec_tol[1] += 1,
2 => sec_tol[2] += 1,
3 => sec_tol[3] += 1,
4 => sec_tol[4] += 1,
_ => {}
}

//println!();

// 从9个数字中随机选出3个
let final_group: Vec<u32> = sec_vec.choose_multiple(&mut rng, 3).cloned().collect();

//println!("随机选出的3个数字为: {:?}", final_group);
//writeln!(&mut log_file, "随机选出的3个数字为: {:?}", final_group).unwrap();
//println!();

// 打印每组并统计恶意节点的出现次数
total_malicious_count = 0;
for (_i, num) in final_group.iter().enumerate() {
let mut malicious_count = 0;
if num % 7 == 0 {
malicious_count += 1;
}
total_malicious_count += malicious_count;
//println!("第{}组: {:?}, 恶意节点数: {}", i + 1, num, malicious_count);
//writeln!(&mut log_file, "第{}组: {:?}, 恶意节点数: {}", i + 1, num, malicious_count).unwrap();
}
//println!("总共检测到 {} 个恶意节点", total_malicious_count);
//writeln!(&mut log_file, "总共检测到 {} 个恶意节点", total_malicious_count).unwrap();
match total_malicious_count {
0 => ird_tol[0] += 1,
1 => ird_tol[1] += 1,
2 => ird_tol[2] += 1,
3 => ird_tol[3] += 1,
_ => {}
}
//println!();
//writeln!(&mut log_file, "").unwrap();
}

在循环外进行最终统计,实际上在日志中看到的就是这部分内容(可以用循环代替,这里笔者懒得动了,所以看着很冗余)顺便一提,虽然 rust 会自己把打开的文件关掉,但你不能不记得这件事。就像结婚纪念日,你对象可以不提,但你自己得记住,这是态度问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 统计总共检测到恶意节点的次数
writeln!(&mut log_file, "第二次分配后的恶意节点数统计:").unwrap();
writeln!(&mut log_file, "0个恶意节点的次数: {}" , sec_tol[0]).unwrap();
writeln!(&mut log_file, "1个恶意节点的次数: {}" , sec_tol[1]).unwrap();
writeln!(&mut log_file, "2个恶意节点的次数: {}" , sec_tol[2]).unwrap();
writeln!(&mut log_file, "3个恶意节点的次数: {}" , sec_tol[3]).unwrap();

writeln!(&mut log_file, "").unwrap();

writeln!(&mut log_file, "第三次分配后的恶意节点数统计:").unwrap();
writeln!(&mut log_file, "0个恶意节点的次数: {}" , ird_tol[0]).unwrap();
writeln!(&mut log_file, "1个恶意节点的次数: {}" , ird_tol[1]).unwrap();
writeln!(&mut log_file, "2个恶意节点的次数: {}" , ird_tol[2]).unwrap();
writeln!(&mut log_file, "3个恶意节点的次数: {}" , ird_tol[3]).unwrap();

log_file.flush().unwrap();

最后附上一张输出记录的整合图,我跑了两次模拟然后把记录合并

logs

可以看到正式委员会中存在2个恶意节点的概率相对来说还是比较高的,这算是一个比较大的风险。

改进方法:

  1. 扩大正式委员会的数量,对恶意节点进行稀释
  2. 调整次级分片中节点数量的比例,在平衡交易效率的同时降低受恶意节点的干扰

本次实验中并没有模拟交易效率,这部分内容可能在之后放出


RapidChain选举网络_Demo
http://example.com/2024/08/23/RapidChain选举网络-Demo/
作者
Tsglz
发布于
2024年8月23日
许可协议