Skip to content

Commit 8738030

Browse files
committed
Add basic chunk format and compression/decompression
1 parent 96641fb commit 8738030

File tree

4 files changed

+159
-0
lines changed

4 files changed

+159
-0
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

util/merkle/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ hashdb = {path = "../hashdb" }
1010
codechain-crypto = { git = "https://github.com/CodeChain-io/rust-codechain-crypto.git", version = "0.1" }
1111
primitives = { git = "https://github.com/CodeChain-io/rust-codechain-primitives.git", version = "0.4" }
1212
rlp = {path = "../rlp" }
13+
rlp_derive = { path = "../rlp_derive" }
14+
snap = "0.2"
1315

1416
[dev-dependencies]
1517
trie-standardmap = { path = "../trie-standardmap" }

util/merkle/src/chunk.rs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
// Copyright 2019 Kodebox, Inc.
2+
// This file is part of CodeChain.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as
6+
// published by the Free Software Foundation, either version 3 of the
7+
// License, or (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
use std::io::Error as IoError;
18+
use std::io::{Cursor, Read, Write};
19+
20+
use primitives::H256;
21+
use rlp::{DecoderError as RlpDecoderError, RlpStream, UntrustedRlp};
22+
use snap;
23+
24+
struct ChunkDecompressor<R> {
25+
read: R,
26+
}
27+
28+
impl<R> ChunkDecompressor<R> {
29+
fn new(read: R) -> Self {
30+
ChunkDecompressor {
31+
read,
32+
}
33+
}
34+
}
35+
36+
impl<'a> ChunkDecompressor<Cursor<&'a [u8]>> {
37+
fn from_slice(slice: &'a [u8]) -> Self {
38+
ChunkDecompressor::new(Cursor::new(slice))
39+
}
40+
}
41+
42+
impl<R> ChunkDecompressor<R>
43+
where
44+
R: Read + Clone,
45+
{
46+
fn decompress(self) -> Result<RawChunk, Error> {
47+
let mut buf = Vec::new();
48+
49+
let mut snappy = snap::Reader::new(self.read);
50+
snappy.read_to_end(&mut buf)?;
51+
52+
let rlp = UntrustedRlp::new(&buf);
53+
Ok(RawChunk {
54+
nodes: rlp.as_list()?,
55+
})
56+
}
57+
}
58+
59+
struct ChunkCompressor<W> {
60+
write: W,
61+
}
62+
63+
impl<W> ChunkCompressor<W> {
64+
fn new(write: W) -> Self {
65+
ChunkCompressor {
66+
write,
67+
}
68+
}
69+
}
70+
71+
impl<W> ChunkCompressor<W>
72+
where
73+
W: Write,
74+
{
75+
fn compress(self, nodes: &[TerminalNode]) -> Result<(), Error> {
76+
let mut rlp = RlpStream::new_list(nodes.len());
77+
for node in nodes {
78+
rlp.append(node);
79+
}
80+
let mut snappy = snap::Writer::new(self.write);
81+
snappy.write_all(rlp.as_raw())?;
82+
Ok(())
83+
}
84+
}
85+
86+
#[test]
87+
fn test_compress_decompress() {
88+
let terminal_nodes = vec![
89+
TerminalNode {
90+
prefix_path: b"12345".to_vec(),
91+
node_rlp: b"45678".to_vec(),
92+
},
93+
TerminalNode {
94+
prefix_path: b"56789".to_vec(),
95+
node_rlp: b"123abc".to_vec(),
96+
},
97+
];
98+
99+
let mut buffer = Vec::new();
100+
ChunkCompressor::new(&mut buffer).compress(&terminal_nodes).unwrap();
101+
let decompressed = ChunkDecompressor::from_slice(&buffer).decompress().unwrap();
102+
103+
assert_eq!(terminal_nodes, decompressed.nodes);
104+
}
105+
106+
type Prefix = Vec<u8>;
107+
108+
#[derive(RlpEncodable, RlpDecodable, Eq, PartialEq, Debug)]
109+
pub struct TerminalNode {
110+
pub prefix_path: Prefix,
111+
pub node_rlp: Vec<u8>,
112+
}
113+
114+
pub struct RawChunk {
115+
nodes: Vec<TerminalNode>,
116+
}
117+
118+
struct Metadata {
119+
root: H256,
120+
prefix: Prefix,
121+
}
122+
123+
impl RawChunk {
124+
fn recover(&self, metadata: Metadata) -> Result<Chunk, ()> {
125+
unimplemented!();
126+
}
127+
}
128+
129+
struct Chunk {
130+
metadata: Metadata,
131+
nodes: Vec<(H256, Vec<u8>)>,
132+
unresolved_metadata: Vec<Metadata>,
133+
}
134+
135+
#[derive(Debug)]
136+
enum Error {
137+
IoError(IoError),
138+
RlpDecoderError(RlpDecoderError),
139+
}
140+
141+
impl From<IoError> for Error {
142+
fn from(err: IoError) -> Self {
143+
Error::IoError(err)
144+
}
145+
}
146+
147+
impl From<RlpDecoderError> for Error {
148+
fn from(err: RlpDecoderError) -> Self {
149+
Error::RlpDecoderError(err)
150+
}
151+
}

util/merkle/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ extern crate hashdb;
2121
extern crate memorydb;
2222
extern crate primitives;
2323
extern crate rlp;
24+
#[macro_use]
25+
extern crate rlp_derive;
26+
extern crate snap;
2427

2528
#[cfg(test)]
2629
extern crate trie_standardmap as standardmap;
@@ -31,6 +34,7 @@ use ccrypto::BLAKE_NULL_RLP;
3134
use hashdb::{DBValue, HashDB};
3235
use primitives::H256;
3336

37+
pub mod chunk;
3438
mod nibbleslice;
3539
pub mod node;
3640
mod skewed;

0 commit comments

Comments
 (0)