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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use elastic_array::ElasticArray128;
use ethereum_types::H256;
use hash_db::Hasher;
use keccak_hasher::KeccakHasher;
use rlp::{DecoderError, Prototype, Rlp, RlpStream};
use std::marker::PhantomData;
use trie::{node::Node, ChildReference, NibbleSlice, NodeCodec};
#[derive(Default, Clone)]
pub struct RlpNodeCodec<H: Hasher> {
mark: PhantomData<H>,
}
const HASHED_NULL_NODE_BYTES: [u8; 32] = [
0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x55, 0xa6, 0xff, 0x83, 0x45, 0xe6, 0x92, 0xc0, 0xf8, 0x6e,
0x5b, 0x48, 0xe0, 0x1b, 0x99, 0x6c, 0xad, 0xc0, 0x01, 0x62, 0x2f, 0xb5, 0xe3, 0x63, 0xb4, 0x21,
];
const HASHED_NULL_NODE: H256 = H256(HASHED_NULL_NODE_BYTES);
impl NodeCodec<KeccakHasher> for RlpNodeCodec<KeccakHasher> {
type Error = DecoderError;
fn hashed_null_node() -> <KeccakHasher as Hasher>::Out {
HASHED_NULL_NODE
}
fn decode(data: &[u8]) -> ::std::result::Result<Node, Self::Error> {
let r = Rlp::new(data);
match r.prototype()? {
Prototype::List(2) => match NibbleSlice::from_encoded(r.at(0)?.data()?) {
(slice, true) => Ok(Node::Leaf(slice, r.at(1)?.data()?)),
(slice, false) => Ok(Node::Extension(slice, r.at(1)?.as_raw())),
},
Prototype::List(17) => {
let mut nodes = [None as Option<&[u8]>; 16];
for i in 0..16 {
let v = r.at(i)?;
if v.is_empty() {
nodes[i] = None;
} else {
nodes[i] = Some(v.as_raw());
}
}
Ok(Node::Branch(
nodes,
if r.at(16)?.is_empty() {
None
} else {
Some(r.at(16)?.data()?)
},
))
}
Prototype::Data(0) => Ok(Node::Empty),
_ => Err(DecoderError::Custom("Rlp is not valid.")),
}
}
fn try_decode_hash(data: &[u8]) -> Option<<KeccakHasher as Hasher>::Out> {
let r = Rlp::new(data);
if r.is_data() && r.size() == KeccakHasher::LENGTH {
Some(r.as_val().expect("Hash is the correct size; qed"))
} else {
None
}
}
fn is_empty_node(data: &[u8]) -> bool {
Rlp::new(data).is_empty()
}
fn empty_node() -> Vec<u8> {
let mut stream = RlpStream::new();
stream.append_empty_data();
stream.drain()
}
fn leaf_node(partial: &[u8], value: &[u8]) -> Vec<u8> {
let mut stream = RlpStream::new_list(2);
stream.append(&partial);
stream.append(&value);
stream.drain()
}
fn ext_node(
partial: &[u8],
child_ref: ChildReference<<KeccakHasher as Hasher>::Out>,
) -> Vec<u8> {
let mut stream = RlpStream::new_list(2);
stream.append(&partial);
match child_ref {
ChildReference::Hash(h) => stream.append(&h),
ChildReference::Inline(inline_data, len) => {
let bytes = &AsRef::<[u8]>::as_ref(&inline_data)[..len];
stream.append_raw(bytes, 1)
}
};
stream.drain()
}
fn branch_node<I>(children: I, value: Option<ElasticArray128<u8>>) -> Vec<u8>
where
I: IntoIterator<Item = Option<ChildReference<<KeccakHasher as Hasher>::Out>>>,
{
let mut stream = RlpStream::new_list(17);
for child_ref in children {
match child_ref {
Some(c) => match c {
ChildReference::Hash(h) => stream.append(&h),
ChildReference::Inline(inline_data, len) => {
let bytes = &AsRef::<[u8]>::as_ref(&inline_data)[..len];
stream.append_raw(bytes, 1)
}
},
None => stream.append_empty_data(),
};
}
if let Some(value) = value {
stream.append(&&*value);
} else {
stream.append_empty_data();
}
stream.drain()
}
}