mirror of
https://github.com/romanz/electrs.git
synced 2024-11-19 09:54:09 +01:00
Move HeaderList stuff to 'util' module
This commit is contained in:
parent
0c4e500fb8
commit
33f68509f8
@ -11,8 +11,7 @@ use std::fs;
|
||||
use std::io::{BufRead, BufReader, Write};
|
||||
use std::net::TcpStream;
|
||||
|
||||
use index::HeaderList;
|
||||
use types::HeaderMap;
|
||||
use util::{HeaderList, HeaderMap};
|
||||
|
||||
error_chain!{}
|
||||
|
||||
|
111
src/index.rs
111
src/index.rs
@ -8,124 +8,17 @@ use crypto::digest::Digest;
|
||||
use crypto::sha2::Sha256;
|
||||
use log::Level;
|
||||
use pbr;
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt;
|
||||
use std::io::{stderr, Stderr};
|
||||
use std::iter::FromIterator;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::time::{Duration, Instant};
|
||||
use time;
|
||||
|
||||
use daemon::Daemon;
|
||||
use store::{Row, Store};
|
||||
use types::{full_hash, hash_prefix, Bytes, FullHash, HashPrefix, HeaderMap, HASH_PREFIX_LEN};
|
||||
use util::{full_hash, hash_prefix, Bytes, FullHash, HashPrefix, HeaderEntry, HeaderList,
|
||||
HeaderMap, HASH_PREFIX_LEN};
|
||||
|
||||
type ProgressBar = pbr::ProgressBar<Stderr>;
|
||||
|
||||
// TODO: move to a separate file (to break index<->daemon dependency)
|
||||
#[derive(Eq, PartialEq, Clone)]
|
||||
pub struct HeaderEntry {
|
||||
height: usize,
|
||||
hash: Sha256dHash,
|
||||
header: BlockHeader,
|
||||
}
|
||||
|
||||
impl HeaderEntry {
|
||||
pub fn hash(&self) -> &Sha256dHash {
|
||||
&self.hash
|
||||
}
|
||||
|
||||
pub fn header(&self) -> &BlockHeader {
|
||||
&self.header
|
||||
}
|
||||
|
||||
pub fn height(&self) -> usize {
|
||||
self.height
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HeaderList {
|
||||
headers: Vec<HeaderEntry>,
|
||||
tip: Sha256dHash,
|
||||
}
|
||||
|
||||
impl HeaderList {
|
||||
pub fn build(mut header_map: HeaderMap, mut blockhash: Sha256dHash) -> HeaderList {
|
||||
let null_hash = Sha256dHash::default();
|
||||
let tip = blockhash;
|
||||
struct HashedHeader {
|
||||
blockhash: Sha256dHash,
|
||||
header: BlockHeader,
|
||||
}
|
||||
let mut hashed_headers = VecDeque::<HashedHeader>::new();
|
||||
while blockhash != null_hash {
|
||||
let header: BlockHeader = header_map.remove(&blockhash).unwrap();
|
||||
hashed_headers.push_front(HashedHeader { blockhash, header });
|
||||
blockhash = header.prev_blockhash;
|
||||
}
|
||||
if !header_map.is_empty() {
|
||||
warn!("orphaned blocks: {:?}", header_map);
|
||||
}
|
||||
HeaderList {
|
||||
headers: hashed_headers
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(height, hashed_header)| HeaderEntry {
|
||||
height: height,
|
||||
hash: hashed_header.blockhash,
|
||||
header: hashed_header.header,
|
||||
})
|
||||
.collect(),
|
||||
tip: tip,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn empty() -> HeaderList {
|
||||
HeaderList {
|
||||
headers: vec![],
|
||||
tip: Sha256dHash::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn equals(&self, other: &HeaderList) -> bool {
|
||||
self.headers.last() == other.headers.last()
|
||||
}
|
||||
|
||||
pub fn headers(&self) -> &[HeaderEntry] {
|
||||
&self.headers
|
||||
}
|
||||
|
||||
pub fn tip(&self) -> Sha256dHash {
|
||||
self.tip
|
||||
}
|
||||
|
||||
pub fn height(&self) -> usize {
|
||||
self.headers.len() - 1
|
||||
}
|
||||
|
||||
pub fn as_map(&self) -> HeaderMap {
|
||||
HeaderMap::from_iter(self.headers.iter().map(|entry| (entry.hash, entry.header)))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for HeaderList {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let last_block_time = self.headers.last().map_or("N/A".to_string(), |h| {
|
||||
time::at_utc(time::Timespec::new(h.header.time as i64, 0))
|
||||
.rfc3339()
|
||||
.to_string()
|
||||
});
|
||||
|
||||
write!(
|
||||
f,
|
||||
"best={} height={} @ {}",
|
||||
self.height(),
|
||||
self.tip(),
|
||||
last_block_time,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct TxInKey {
|
||||
pub code: u8,
|
||||
|
@ -29,5 +29,4 @@ pub mod mempool;
|
||||
pub mod query;
|
||||
pub mod rpc;
|
||||
pub mod store;
|
||||
pub mod types;
|
||||
pub mod util;
|
||||
|
@ -6,10 +6,10 @@ use itertools::enumerate;
|
||||
use std::sync::RwLock;
|
||||
|
||||
use daemon::Daemon;
|
||||
use index::{compute_script_hash, HeaderEntry, Index, TxInRow, TxOutRow, TxRow};
|
||||
use index::{compute_script_hash, Index, TxInRow, TxOutRow, TxRow};
|
||||
use mempool::Tracker;
|
||||
use store::Store;
|
||||
use types::HashPrefix;
|
||||
use util::{HashPrefix, HeaderEntry};
|
||||
|
||||
error_chain!{}
|
||||
|
||||
|
@ -14,7 +14,7 @@ use std::net::{SocketAddr, TcpListener, TcpStream};
|
||||
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
||||
|
||||
use query::{Query, Status};
|
||||
use types::FullHash;
|
||||
use util::FullHash;
|
||||
|
||||
error_chain!{}
|
||||
|
||||
|
@ -2,7 +2,7 @@ use bitcoin::blockdata::block::BlockHeader;
|
||||
use bitcoin::network::serialize::deserialize;
|
||||
use rocksdb;
|
||||
|
||||
use types::Bytes;
|
||||
use util::Bytes;
|
||||
|
||||
pub struct Store {
|
||||
db: rocksdb::DB,
|
||||
|
21
src/types.rs
21
src/types.rs
@ -1,21 +0,0 @@
|
||||
use bitcoin::blockdata::block::BlockHeader;
|
||||
use bitcoin::util::hash::Sha256dHash;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub type Bytes = Vec<u8>;
|
||||
pub type HeaderMap = HashMap<Sha256dHash, BlockHeader>;
|
||||
|
||||
// TODO: consolidate serialization/deserialize code for bincode/bitcoin.
|
||||
const HASH_LEN: usize = 32;
|
||||
pub const HASH_PREFIX_LEN: usize = 8;
|
||||
|
||||
pub type FullHash = [u8; HASH_LEN];
|
||||
pub type HashPrefix = [u8; HASH_PREFIX_LEN];
|
||||
|
||||
pub fn hash_prefix(hash: &[u8]) -> HashPrefix {
|
||||
array_ref![hash, 0, HASH_PREFIX_LEN].clone()
|
||||
}
|
||||
|
||||
pub fn full_hash(hash: &[u8]) -> FullHash {
|
||||
array_ref![hash, 0, HASH_LEN].clone()
|
||||
}
|
127
src/util.rs
127
src/util.rs
@ -1 +1,128 @@
|
||||
use bitcoin::blockdata::block::BlockHeader;
|
||||
use bitcoin::util::hash::Sha256dHash;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt;
|
||||
use std::iter::FromIterator;
|
||||
use time;
|
||||
|
||||
pub type Bytes = Vec<u8>;
|
||||
pub type HeaderMap = HashMap<Sha256dHash, BlockHeader>;
|
||||
|
||||
// TODO: consolidate serialization/deserialize code for bincode/bitcoin.
|
||||
const HASH_LEN: usize = 32;
|
||||
pub const HASH_PREFIX_LEN: usize = 8;
|
||||
|
||||
pub type FullHash = [u8; HASH_LEN];
|
||||
pub type HashPrefix = [u8; HASH_PREFIX_LEN];
|
||||
|
||||
pub fn hash_prefix(hash: &[u8]) -> HashPrefix {
|
||||
array_ref![hash, 0, HASH_PREFIX_LEN].clone()
|
||||
}
|
||||
|
||||
pub fn full_hash(hash: &[u8]) -> FullHash {
|
||||
array_ref![hash, 0, HASH_LEN].clone()
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Clone)]
|
||||
pub struct HeaderEntry {
|
||||
height: usize,
|
||||
hash: Sha256dHash,
|
||||
header: BlockHeader,
|
||||
}
|
||||
|
||||
impl HeaderEntry {
|
||||
pub fn hash(&self) -> &Sha256dHash {
|
||||
&self.hash
|
||||
}
|
||||
|
||||
pub fn header(&self) -> &BlockHeader {
|
||||
&self.header
|
||||
}
|
||||
|
||||
pub fn height(&self) -> usize {
|
||||
self.height
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HeaderList {
|
||||
headers: Vec<HeaderEntry>,
|
||||
tip: Sha256dHash,
|
||||
}
|
||||
|
||||
impl HeaderList {
|
||||
pub fn build(mut header_map: HeaderMap, mut blockhash: Sha256dHash) -> HeaderList {
|
||||
let null_hash = Sha256dHash::default();
|
||||
let tip = blockhash;
|
||||
struct HashedHeader {
|
||||
blockhash: Sha256dHash,
|
||||
header: BlockHeader,
|
||||
}
|
||||
let mut hashed_headers = VecDeque::<HashedHeader>::new();
|
||||
while blockhash != null_hash {
|
||||
let header: BlockHeader = header_map.remove(&blockhash).unwrap();
|
||||
hashed_headers.push_front(HashedHeader { blockhash, header });
|
||||
blockhash = header.prev_blockhash;
|
||||
}
|
||||
if !header_map.is_empty() {
|
||||
warn!("orphaned blocks: {:?}", header_map);
|
||||
}
|
||||
HeaderList {
|
||||
headers: hashed_headers
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(height, hashed_header)| HeaderEntry {
|
||||
height: height,
|
||||
hash: hashed_header.blockhash,
|
||||
header: hashed_header.header,
|
||||
})
|
||||
.collect(),
|
||||
tip: tip,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn empty() -> HeaderList {
|
||||
HeaderList {
|
||||
headers: vec![],
|
||||
tip: Sha256dHash::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn equals(&self, other: &HeaderList) -> bool {
|
||||
self.headers.last() == other.headers.last()
|
||||
}
|
||||
|
||||
pub fn headers(&self) -> &[HeaderEntry] {
|
||||
&self.headers
|
||||
}
|
||||
|
||||
pub fn tip(&self) -> Sha256dHash {
|
||||
self.tip
|
||||
}
|
||||
|
||||
pub fn height(&self) -> usize {
|
||||
self.headers.len() - 1
|
||||
}
|
||||
|
||||
pub fn as_map(&self) -> HeaderMap {
|
||||
HeaderMap::from_iter(self.headers.iter().map(|entry| (entry.hash, entry.header)))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for HeaderList {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let last_block_time = self.headers.last().map_or("N/A".to_string(), |h| {
|
||||
time::at_utc(time::Timespec::new(h.header.time as i64, 0))
|
||||
.rfc3339()
|
||||
.to_string()
|
||||
});
|
||||
|
||||
write!(
|
||||
f,
|
||||
"best={} height={} @ {}",
|
||||
self.height(),
|
||||
self.tip(),
|
||||
last_block_time,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user