import module
This commit is contained in:
parent
260986da9c
commit
05ed9567e9
|
@ -6,6 +6,7 @@ dependencies = [
|
||||||
"clap 2.16.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clap 2.16.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"db 0.1.0",
|
"db 0.1.0",
|
||||||
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"import 0.1.0",
|
||||||
"keys 0.1.0",
|
"keys 0.1.0",
|
||||||
"message 0.1.0",
|
"message 0.1.0",
|
||||||
"miner 0.1.0",
|
"miner 0.1.0",
|
||||||
|
@ -219,6 +220,15 @@ dependencies = [
|
||||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "import"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"chain 0.1.0",
|
||||||
|
"primitives 0.1.0",
|
||||||
|
"serialization 0.1.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kernel32-sys"
|
name = "kernel32-sys"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
|
|
@ -17,6 +17,7 @@ script = { path = "script" }
|
||||||
db = { path = "db" }
|
db = { path = "db" }
|
||||||
verification = { path = "verification" }
|
verification = { path = "verification" }
|
||||||
sync = { path = "sync" }
|
sync = { path = "sync" }
|
||||||
|
import = { path = "import" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
path = "pbtc/main.rs"
|
path = "pbtc/main.rs"
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "import"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["debris <marek.kotewicz@gmail.com>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
primitives = { path = "../primitives" }
|
||||||
|
chain = { path = "../chain" }
|
||||||
|
serialization = { path = "../serialization" }
|
|
@ -0,0 +1,68 @@
|
||||||
|
use std::{io, fs, path};
|
||||||
|
use ser::{ReadIterator, deserialize_iterator, Error as ReaderError};
|
||||||
|
use block::Block;
|
||||||
|
use fs::{read_blk_dir, ReadBlkDir};
|
||||||
|
|
||||||
|
pub fn open_blk_file<P>(path: P) -> Result<BlkFile, io::Error> where P: AsRef<path::Path> {
|
||||||
|
let file = try!(fs::File::open(path));
|
||||||
|
let blk_file = BlkFile {
|
||||||
|
reader: deserialize_iterator(file),
|
||||||
|
};
|
||||||
|
Ok(blk_file)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BlkFile {
|
||||||
|
reader: ReadIterator<fs::File, Block>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for BlkFile {
|
||||||
|
type Item = Result<Block, ReaderError>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
self.reader.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open_blk_dir<P>(path: P) -> Result<BlkDir, io::Error> where P: AsRef<path::Path> {
|
||||||
|
let dir_iter = try!(read_blk_dir(path));
|
||||||
|
let blk_dir = BlkDir {
|
||||||
|
dir_iter: dir_iter,
|
||||||
|
current_file: None,
|
||||||
|
};
|
||||||
|
Ok(blk_dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BlkDir {
|
||||||
|
dir_iter: ReadBlkDir,
|
||||||
|
current_file: Option<BlkFile>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for BlkDir {
|
||||||
|
type Item = Result<Block, ReaderError>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
// TODO: use chained iterators instead
|
||||||
|
let next_file = match self.current_file {
|
||||||
|
Some(ref mut file) => match file.next() {
|
||||||
|
Some(block) => return Some(block),
|
||||||
|
None => self.dir_iter.next(),
|
||||||
|
},
|
||||||
|
None => self.dir_iter.next(),
|
||||||
|
};
|
||||||
|
|
||||||
|
match next_file {
|
||||||
|
Some(Ok(next_file)) => {
|
||||||
|
self.current_file = match open_blk_file(next_file.path) {
|
||||||
|
Err(_) => return Some(Err(ReaderError::MalformedData)),
|
||||||
|
Ok(file) => Some(file),
|
||||||
|
};
|
||||||
|
self.next()
|
||||||
|
},
|
||||||
|
Some(Err(_)) => {
|
||||||
|
Some(Err(ReaderError::MalformedData))
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
use std::io;
|
||||||
|
use hash::H32;
|
||||||
|
use ser::{Deserializable, Reader, Error as ReaderError};
|
||||||
|
use chain;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct Block {
|
||||||
|
magic: H32,
|
||||||
|
block_size: u32,
|
||||||
|
block: chain::Block,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deserializable for Block {
|
||||||
|
fn deserialize<T>(reader: &mut Reader<T>) -> Result<Self, ReaderError> where T: io::Read {
|
||||||
|
let block = Block {
|
||||||
|
magic: try!(reader.read()),
|
||||||
|
block_size: try!(reader.read()),
|
||||||
|
block: try!(reader.read()),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(block)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
use std::{io, fs, path};
|
||||||
|
|
||||||
|
/// Creates an iterator over all blk .dat files
|
||||||
|
pub fn read_blk_dir<P>(path: P) -> Result<ReadBlkDir, io::Error> where P: AsRef<path::Path> {
|
||||||
|
let read_blk_dir = ReadBlkDir {
|
||||||
|
read_dir: try!(fs::read_dir(path)),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(read_blk_dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ReadBlkDir {
|
||||||
|
read_dir: fs::ReadDir,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BlkEntry {
|
||||||
|
pub path: path::PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_blk_file_name(file_name: &str) -> bool {
|
||||||
|
if file_name.len() != 12 || !file_name.starts_with("blk") || !file_name.ends_with(".dat") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_name[3..8].parse::<u32>().is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlkEntry {
|
||||||
|
fn from_dir_entry(dir_entry: fs::DirEntry) -> Option<Self> {
|
||||||
|
match dir_entry.metadata() {
|
||||||
|
Err(_) => return None,
|
||||||
|
Ok(ref metadata) => {
|
||||||
|
if !metadata.is_file() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match dir_entry.file_name().into_string() {
|
||||||
|
Err(_) => return None,
|
||||||
|
Ok(ref file_name) => {
|
||||||
|
if !is_blk_file_name(file_name) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let entry = BlkEntry {
|
||||||
|
path: dir_entry.path(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for ReadBlkDir {
|
||||||
|
type Item = Result<BlkEntry, io::Error>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let mut result = None;
|
||||||
|
while result.is_none() {
|
||||||
|
match self.read_dir.next() {
|
||||||
|
None => return None,
|
||||||
|
Some(Err(err)) => return Some(Err(err)),
|
||||||
|
Some(Ok(entry)) => {
|
||||||
|
result = BlkEntry::from_dir_entry(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.map(Ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::is_blk_file_name;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_blk_file_name() {
|
||||||
|
assert!(is_blk_file_name("blk00000.dat"));
|
||||||
|
assert!(is_blk_file_name("blk00232.dat"));
|
||||||
|
assert!(!is_blk_file_name("blk0000.dat"));
|
||||||
|
assert!(!is_blk_file_name("blk00000.daw"));
|
||||||
|
assert!(!is_blk_file_name("blk00032.daw"));
|
||||||
|
assert!(!is_blk_file_name("blk000ff.dat"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
extern crate primitives;
|
||||||
|
extern crate serialization as ser;
|
||||||
|
extern crate chain;
|
||||||
|
|
||||||
|
mod blk;
|
||||||
|
mod block;
|
||||||
|
mod fs;
|
||||||
|
|
||||||
|
pub use primitives::{hash, bytes};
|
||||||
|
|
||||||
|
pub use blk::{open_blk_file, open_blk_dir};
|
|
@ -29,4 +29,9 @@ args:
|
||||||
- diskdb:
|
- diskdb:
|
||||||
long: diskdb
|
long: diskdb
|
||||||
help: Use disk storage instead of in-memory one
|
help: Use disk storage instead of in-memory one
|
||||||
|
- import:
|
||||||
|
long: import
|
||||||
|
value_name: PATH
|
||||||
|
help: Import blocks from bitcoin core database
|
||||||
|
takes_value: true
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ pub struct Config {
|
||||||
pub seednode: Option<String>,
|
pub seednode: Option<String>,
|
||||||
pub print_to_console: bool,
|
pub print_to_console: bool,
|
||||||
pub use_disk_database: bool,
|
pub use_disk_database: bool,
|
||||||
|
pub import_path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(matches: &clap::ArgMatches) -> Result<Config, String> {
|
pub fn parse(matches: &clap::ArgMatches) -> Result<Config, String> {
|
||||||
|
@ -34,6 +35,11 @@ pub fn parse(matches: &clap::ArgMatches) -> Result<Config, String> {
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let import_path = match matches.value_of("import") {
|
||||||
|
Some(s) => Some(try!(s.parse().map_err(|_| "Invalid import path".to_owned()))),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
let config = Config {
|
let config = Config {
|
||||||
print_to_console: print_to_console,
|
print_to_console: print_to_console,
|
||||||
magic: magic,
|
magic: magic,
|
||||||
|
@ -41,6 +47,7 @@ pub fn parse(matches: &clap::ArgMatches) -> Result<Config, String> {
|
||||||
connect: connect,
|
connect: connect,
|
||||||
seednode: seednode,
|
seednode: seednode,
|
||||||
use_disk_database: use_disk_database,
|
use_disk_database: use_disk_database,
|
||||||
|
import_path: import_path,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(config)
|
Ok(config)
|
||||||
|
|
13
pbtc/main.rs
13
pbtc/main.rs
|
@ -2,15 +2,16 @@
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
extern crate db;
|
|
||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
|
|
||||||
|
extern crate db;
|
||||||
extern crate chain;
|
extern crate chain;
|
||||||
extern crate keys;
|
extern crate keys;
|
||||||
extern crate script;
|
extern crate script;
|
||||||
extern crate message;
|
extern crate message;
|
||||||
extern crate p2p;
|
extern crate p2p;
|
||||||
extern crate sync;
|
extern crate sync;
|
||||||
|
extern crate import;
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
|
|
||||||
|
@ -54,11 +55,21 @@ fn init_db(db: &Arc<db::Store>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn import_blockchain(db_path: &str) {
|
||||||
|
for _block in import::open_blk_dir(db_path).expect("TODO") {
|
||||||
|
// import logic goes here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn run() -> Result<(), String> {
|
fn run() -> Result<(), String> {
|
||||||
let yaml = load_yaml!("cli.yml");
|
let yaml = load_yaml!("cli.yml");
|
||||||
let matches = clap::App::from_yaml(yaml).get_matches();
|
let matches = clap::App::from_yaml(yaml).get_matches();
|
||||||
let cfg = try!(config::parse(&matches));
|
let cfg = try!(config::parse(&matches));
|
||||||
|
|
||||||
|
if let Some(ref import_path) = cfg.import_path {
|
||||||
|
import_blockchain(import_path);
|
||||||
|
}
|
||||||
|
|
||||||
let mut el = event_loop();
|
let mut el = event_loop();
|
||||||
|
|
||||||
let p2p_cfg = p2p::Config {
|
let p2p_cfg = p2p::Config {
|
||||||
|
|
|
@ -9,5 +9,5 @@ pub mod stream;
|
||||||
pub use primitives::{hash, bytes};
|
pub use primitives::{hash, bytes};
|
||||||
|
|
||||||
pub use compact_integer::CompactInteger;
|
pub use compact_integer::CompactInteger;
|
||||||
pub use self::reader::{Reader, Deserializable, deserialize, deserialize_iterator, Error};
|
pub use self::reader::{Reader, Deserializable, deserialize, deserialize_iterator, ReadIterator, Error};
|
||||||
pub use self::stream::{Stream, Serializable, serialize, serialized_list_size};
|
pub use self::stream::{Stream, Serializable, serialize, serialized_list_size};
|
||||||
|
|
|
@ -13,5 +13,6 @@ cargo test\
|
||||||
-p script\
|
-p script\
|
||||||
-p serialization\
|
-p serialization\
|
||||||
-p sync\
|
-p sync\
|
||||||
|
-p import\
|
||||||
-p pbtc\
|
-p pbtc\
|
||||||
-p verification
|
-p verification
|
||||||
|
|
Loading…
Reference in New Issue