Skip to content

Commit 438f365

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

File tree

4 files changed

+136
-0
lines changed

4 files changed

+136
-0
lines changed

Cargo.lock

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

sync/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ parking_lot = "0.6.0"
2222
primitives = { git = "https://github.com/CodeChain-io/rust-codechain-primitives.git", version = "0.4" }
2323
rand = "0.6.1"
2424
rlp = { path = "../util/rlp" }
25+
rlp_derive = { path = "../util/rlp_derive" }
2526
snap = "0.2"
2627
time = "0.1"
2728
token-generator = "0.1.0"

sync/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ extern crate never_type;
3737
extern crate primitives;
3838
extern crate rand;
3939
extern crate rlp;
40+
#[macro_use]
41+
extern crate rlp_derive;
4042
extern crate snap;
4143
#[cfg(test)]
4244
extern crate tempfile;
@@ -47,6 +49,7 @@ extern crate trie_standardmap;
4749
extern crate util_error;
4850

4951
mod block;
52+
mod snapshot;
5053
mod transaction;
5154

5255
pub use crate::block::{BlockSyncEvent, BlockSyncExtension, BlockSyncSender};

sync/src/snapshot/mod.rs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
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 rlp::{DecoderError as RlpDecoderError, RlpStream, UntrustedRlp};
21+
use snap;
22+
23+
struct ChunkDecompressor<R> {
24+
read: R,
25+
}
26+
27+
impl<R> ChunkDecompressor<R> {
28+
fn new(read: R) -> Self {
29+
ChunkDecompressor {
30+
read,
31+
}
32+
}
33+
}
34+
35+
impl<'a> ChunkDecompressor<Cursor<&'a [u8]>> {
36+
fn from_slice(slice: &'a [u8]) -> Self {
37+
ChunkDecompressor::new(Cursor::new(slice))
38+
}
39+
}
40+
41+
impl<R> ChunkDecompressor<R>
42+
where
43+
R: Read + Clone,
44+
{
45+
fn decompress(self) -> Result<RawChunk, Error> {
46+
let mut buf = Vec::new();
47+
48+
let mut snappy = snap::Reader::new(self.read);
49+
snappy.read_to_end(&mut buf)?;
50+
51+
let rlp = UntrustedRlp::new(&buf);
52+
Ok(RawChunk {
53+
nodes: rlp.as_list()?,
54+
})
55+
}
56+
}
57+
58+
struct ChunkCompressor<W> {
59+
write: W,
60+
}
61+
62+
impl<W> ChunkCompressor<W> {
63+
fn new(write: W) -> Self {
64+
ChunkCompressor {
65+
write,
66+
}
67+
}
68+
}
69+
70+
impl<W> ChunkCompressor<W>
71+
where
72+
W: Write,
73+
{
74+
fn compress(self, nodes: &[TerminalNode]) -> Result<(), Error> {
75+
let mut rlp = RlpStream::new_list(nodes.len());
76+
for node in nodes {
77+
rlp.append(node);
78+
}
79+
let mut snappy = snap::Writer::new(self.write);
80+
snappy.write_all(rlp.as_raw())?;
81+
Ok(())
82+
}
83+
}
84+
85+
#[test]
86+
fn test_compress_decompress() {
87+
let terminal_nodes = vec![
88+
TerminalNode {
89+
prefix_path: b"12345".to_vec(),
90+
node_rlp: b"45678".to_vec(),
91+
},
92+
TerminalNode {
93+
prefix_path: b"56789".to_vec(),
94+
node_rlp: b"123abc".to_vec(),
95+
},
96+
];
97+
98+
let mut buffer = Vec::new();
99+
ChunkCompressor::new(&mut buffer).compress(&terminal_nodes).unwrap();
100+
let decompressed = ChunkDecompressor::from_slice(&buffer).decompress().unwrap();
101+
102+
assert_eq!(terminal_nodes, decompressed.nodes);
103+
}
104+
105+
#[derive(RlpEncodable, RlpDecodable, Eq, PartialEq, Debug)]
106+
struct TerminalNode {
107+
prefix_path: Vec<u8>,
108+
node_rlp: Vec<u8>,
109+
}
110+
111+
struct RawChunk {
112+
nodes: Vec<TerminalNode>,
113+
}
114+
115+
#[derive(Debug)]
116+
enum Error {
117+
IoError(IoError),
118+
RlpDecoderError(RlpDecoderError),
119+
}
120+
121+
impl From<IoError> for Error {
122+
fn from(err: IoError) -> Self {
123+
Error::IoError(err)
124+
}
125+
}
126+
127+
impl From<RlpDecoderError> for Error {
128+
fn from(err: RlpDecoderError) -> Self {
129+
Error::RlpDecoderError(err)
130+
}
131+
}

0 commit comments

Comments
 (0)