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
115
116
117
118
119
120
121
122
123
124
125
126
127
use crate::h256::H256;
use crate::traits::Hasher;
const MERGE_NORMAL: u8 = 1;
const MERGE_ZEROS: u8 = 2;
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum MergeValue {
Value(H256),
MergeWithZero {
base_node: H256,
zero_bits: H256,
zero_count: u8,
},
}
impl MergeValue {
pub fn from_h256(v: H256) -> Self {
MergeValue::Value(v)
}
pub fn zero() -> Self {
MergeValue::Value(H256::zero())
}
pub fn is_zero(&self) -> bool {
if let MergeValue::Value(v) = self {
return v.is_zero();
}
false
}
pub fn hash<H: Hasher + Default>(&self) -> H256 {
match self {
MergeValue::Value(v) => *v,
MergeValue::MergeWithZero {
base_node,
zero_bits,
zero_count,
} => {
let mut hasher = H::default();
hasher.write_byte(MERGE_ZEROS);
hasher.write_h256(base_node);
hasher.write_h256(zero_bits);
hasher.write_byte(*zero_count);
hasher.finish()
}
}
}
}
pub fn hash_base_node<H: Hasher + Default>(
base_height: u8,
base_key: &H256,
base_value: &H256,
) -> H256 {
let mut hasher = H::default();
hasher.write_byte(base_height);
hasher.write_h256(base_key);
hasher.write_h256(base_value);
hasher.finish()
}
pub fn merge<H: Hasher + Default>(
height: u8,
node_key: &H256,
lhs: &MergeValue,
rhs: &MergeValue,
) -> MergeValue {
if lhs.is_zero() && rhs.is_zero() {
return MergeValue::zero();
}
if lhs.is_zero() {
return merge_with_zero::<H>(height, node_key, rhs, true);
}
if rhs.is_zero() {
return merge_with_zero::<H>(height, node_key, lhs, false);
}
let mut hasher = H::default();
hasher.write_byte(MERGE_NORMAL);
hasher.write_byte(height);
hasher.write_h256(node_key);
hasher.write_h256(&lhs.hash::<H>());
hasher.write_h256(&rhs.hash::<H>());
MergeValue::Value(hasher.finish())
}
fn merge_with_zero<H: Hasher + Default>(
height: u8,
node_key: &H256,
value: &MergeValue,
set_bit: bool,
) -> MergeValue {
match value {
MergeValue::Value(v) => {
let mut zero_bits = H256::zero();
if set_bit {
zero_bits.set_bit(height);
}
let base_node = hash_base_node::<H>(height, node_key, v);
MergeValue::MergeWithZero {
base_node,
zero_bits,
zero_count: 1,
}
}
MergeValue::MergeWithZero {
base_node,
zero_bits,
zero_count,
} => {
let mut zero_bits = *zero_bits;
if set_bit {
zero_bits.set_bit(height);
}
MergeValue::MergeWithZero {
base_node: *base_node,
zero_bits,
zero_count: zero_count.wrapping_add(1),
}
}
}
}