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::io::{BufRead, BufReader, Write};
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
|
|
||||||
use index::HeaderList;
|
use util::{HeaderList, HeaderMap};
|
||||||
use types::HeaderMap;
|
|
||||||
|
|
||||||
error_chain!{}
|
error_chain!{}
|
||||||
|
|
||||||
|
111
src/index.rs
111
src/index.rs
@ -8,124 +8,17 @@ use crypto::digest::Digest;
|
|||||||
use crypto::sha2::Sha256;
|
use crypto::sha2::Sha256;
|
||||||
use log::Level;
|
use log::Level;
|
||||||
use pbr;
|
use pbr;
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::fmt;
|
|
||||||
use std::io::{stderr, Stderr};
|
use std::io::{stderr, Stderr};
|
||||||
use std::iter::FromIterator;
|
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use time;
|
|
||||||
|
|
||||||
use daemon::Daemon;
|
use daemon::Daemon;
|
||||||
use store::{Row, Store};
|
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>;
|
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)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct TxInKey {
|
pub struct TxInKey {
|
||||||
pub code: u8,
|
pub code: u8,
|
||||||
|
@ -29,5 +29,4 @@ pub mod mempool;
|
|||||||
pub mod query;
|
pub mod query;
|
||||||
pub mod rpc;
|
pub mod rpc;
|
||||||
pub mod store;
|
pub mod store;
|
||||||
pub mod types;
|
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
@ -6,10 +6,10 @@ use itertools::enumerate;
|
|||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
use daemon::Daemon;
|
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 mempool::Tracker;
|
||||||
use store::Store;
|
use store::Store;
|
||||||
use types::HashPrefix;
|
use util::{HashPrefix, HeaderEntry};
|
||||||
|
|
||||||
error_chain!{}
|
error_chain!{}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ use std::net::{SocketAddr, TcpListener, TcpStream};
|
|||||||
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
||||||
|
|
||||||
use query::{Query, Status};
|
use query::{Query, Status};
|
||||||
use types::FullHash;
|
use util::FullHash;
|
||||||
|
|
||||||
error_chain!{}
|
error_chain!{}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use bitcoin::blockdata::block::BlockHeader;
|
|||||||
use bitcoin::network::serialize::deserialize;
|
use bitcoin::network::serialize::deserialize;
|
||||||
use rocksdb;
|
use rocksdb;
|
||||||
|
|
||||||
use types::Bytes;
|
use util::Bytes;
|
||||||
|
|
||||||
pub struct Store {
|
pub struct Store {
|
||||||
db: rocksdb::DB,
|
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