-
Notifications
You must be signed in to change notification settings - Fork 45
/
Copy pathrlp.js
66 lines (54 loc) · 2.14 KB
/
rlp.js
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
// The RLP format
// Serialization and deserialization for the BytesTree type, under the following grammar:
// | First byte | Meaning |
// | ---------- | -------------------------------------------------------------------------- |
// | 0 to 127 | HEX(leaf) |
// | 128 to 183 | HEX(length_of_leaf + 128) + HEX(leaf) |
// | 184 to 191 | HEX(length_of_length_of_leaf + 128 + 55) + HEX(length_of_leaf) + HEX(leaf) |
// | 192 to 247 | HEX(length_of_node + 192) + HEX(node) |
// | 248 to 255 | HEX(length_of_length_of_node + 128 + 55) + HEX(length_of_node) + HEX(node) |
const encode = tree => {
const padEven = str => str.length % 2 === 0 ? str : "0" + str;
const uint = num => padEven(num.toString(16));
const length = (len, add) => len < 56 ? uint(add + len) : uint(add + uint(len).length / 2 + 55) + uint(len);
const dataTree = tree => {
if (typeof tree === "string") {
const hex = tree.slice(2);
const pre = hex.length != 2 || hex >= "80" ? length(hex.length / 2, 128) : "";
return pre + hex;
} else {
const hex = tree.map(dataTree).join("");
const pre = length(hex.length / 2, 192);
return pre + hex;
}
};
return "0x" + dataTree(tree);
};
const decode = hex => {
let i = 2;
const parseTree = () => {
if (i >= hex.length) throw "";
const head = hex.slice(i, i + 2);
return head < "80" ? (i += 2, "0x" + head) : head < "c0" ? parseHex() : parseList();
};
const parseLength = () => {
const len = parseInt(hex.slice(i, i += 2), 16) % 64;
return len < 56 ? len : parseInt(hex.slice(i, i += (len - 55) * 2), 16);
};
const parseHex = () => {
const len = parseLength();
return "0x" + hex.slice(i, i += len * 2);
};
const parseList = () => {
const lim = parseLength() * 2 + i;
let list = [];
while (i < lim) list.push(parseTree());
return list;
};
try {
return parseTree();
} catch (e) {
return [];
}
};
module.exports = { encode, decode };