1
0
Fork 0
mirror of https://github.com/romanz/electrs.git synced 2025-02-24 06:57:53 +01:00

Refactor rows' serialization into index module

This commit is contained in:
Roman Zeyde 2018-05-15 15:23:51 +03:00
parent 935467e6b4
commit b0fb4d4367
No known key found for this signature in database
GPG key ID: 87CAE5FA46917CBB
2 changed files with 115 additions and 66 deletions

View file

@ -17,7 +17,7 @@ use time;
use daemon::Daemon;
use store::{Row, Store};
use types::{full_hash, hash_prefix, FullHash, HashPrefix, HeaderMap};
use types::{full_hash, hash_prefix, Bytes, FullHash, HashPrefix, HeaderMap, HASH_PREFIX_LEN};
// TODO: move to a separate file (to break index<->daemon dependency)
#[derive(Eq, PartialEq, Clone)]
@ -103,6 +103,38 @@ pub struct TxInRow {
pub txid_prefix: HashPrefix,
}
impl TxInRow {
pub fn new(txid: &Sha256dHash, input: &TxIn) -> TxInRow {
TxInRow {
key: TxInKey {
code: b'I',
prev_hash_prefix: hash_prefix(&input.prev_hash[..]),
prev_index: input.prev_index as u16,
},
txid_prefix: hash_prefix(&txid[..]),
}
}
pub fn filter(txid: &Sha256dHash, output_index: usize) -> Bytes {
bincode::serialize(&TxInKey {
code: b'I',
prev_hash_prefix: hash_prefix(&txid[..]),
prev_index: output_index as u16,
}).unwrap()
}
pub fn to_row(&self) -> Row {
Row {
key: bincode::serialize(&self).unwrap(),
value: vec![],
}
}
pub fn from_row(row: &Row) -> TxInRow {
bincode::deserialize(&row.key).expect("failed to parse TxInRow")
}
}
#[derive(Serialize, Deserialize)]
pub struct TxOutKey {
code: u8,
@ -115,12 +147,77 @@ pub struct TxOutRow {
pub txid_prefix: HashPrefix,
}
impl TxOutRow {
pub fn new(txid: &Sha256dHash, output: &TxOut) -> TxOutRow {
TxOutRow {
key: TxOutKey {
code: b'O',
script_hash_prefix: hash_prefix(&compute_script_hash(&output.script_pubkey[..])),
},
txid_prefix: hash_prefix(&txid[..]),
}
}
pub fn filter(script_hash: &[u8]) -> Bytes {
bincode::serialize(&TxOutKey {
code: b'O',
script_hash_prefix: hash_prefix(&script_hash[..HASH_PREFIX_LEN]),
}).unwrap()
}
pub fn to_row(&self) -> Row {
Row {
key: bincode::serialize(&self).unwrap(),
value: vec![],
}
}
pub fn from_row(row: &Row) -> TxOutRow {
bincode::deserialize(&row.key).expect("failed to parse TxOutRow")
}
}
#[derive(Serialize, Deserialize)]
pub struct TxKey {
code: u8,
pub txid: FullHash,
}
pub struct TxRow {
pub key: TxKey,
pub height: u32, // value
}
impl TxRow {
pub fn new(txid: &Sha256dHash, height: u32) -> TxRow {
TxRow {
key: TxKey {
code: b'T',
txid: full_hash(&txid[..]),
},
height: height,
}
}
pub fn filter(txid_prefix: &HashPrefix) -> Bytes {
[b"T", &txid_prefix[..]].concat()
}
pub fn to_row(&self) -> Row {
Row {
key: bincode::serialize(&self.key).unwrap(),
value: bincode::serialize(&self.height).unwrap(),
}
}
pub fn from_row(row: &Row) -> TxRow {
TxRow {
key: bincode::deserialize(&row.key).expect("failed to parse TxKey"),
height: bincode::deserialize(&row.value).expect("failed to parse height"),
}
}
}
#[derive(Serialize, Deserialize)]
pub struct BlockKey {
code: u8,
@ -135,43 +232,6 @@ pub fn compute_script_hash(data: &[u8]) -> FullHash {
hash
}
fn txin_row(input: &TxIn, txid: &Sha256dHash) -> Row {
Row {
key: bincode::serialize(&TxInRow {
key: TxInKey {
code: b'I',
prev_hash_prefix: hash_prefix(&input.prev_hash[..]),
prev_index: input.prev_index as u16,
},
txid_prefix: hash_prefix(&txid[..]),
}).unwrap(),
value: vec![],
}
}
fn txout_row(output: &TxOut, txid: &Sha256dHash) -> Row {
Row {
key: bincode::serialize(&TxOutRow {
key: TxOutKey {
code: b'O',
script_hash_prefix: hash_prefix(&compute_script_hash(&output.script_pubkey[..])),
},
txid_prefix: hash_prefix(&txid[..]),
}).unwrap(),
value: vec![],
}
}
fn tx_row(txid: &Sha256dHash, height: usize) -> Row {
Row {
key: bincode::serialize(&TxKey {
code: b'T',
txid: full_hash(&txid[..]),
}).unwrap(),
value: bincode::serialize(&(height as u32)).unwrap(),
}
}
fn block_rows(block: &Block) -> Vec<Row> {
let blockhash = block.bitcoin_hash();
vec![
@ -198,13 +258,13 @@ fn index_block(block: &Block, height: usize) -> Vec<Row> {
if input.prev_hash == null_hash {
continue;
}
rows.push(txin_row(&input, &txid));
rows.push(TxInRow::new(&txid, &input).to_row());
}
for output in &tx.output {
rows.push(txout_row(&output, &txid))
rows.push(TxOutRow::new(&txid, &output).to_row());
}
// Persist transaction ID and confirmed height
rows.push(tx_row(&txid, height))
rows.push(TxRow::new(&txid, height as u32).to_row());
}
// Persist block hash and header
rows.extend(block_rows(&block));

View file

@ -1,4 +1,3 @@
use bincode;
use bitcoin::blockdata::block::{Block, BlockHeader};
use bitcoin::blockdata::transaction::Transaction;
use bitcoin::network::serialize::deserialize;
@ -6,9 +5,9 @@ use bitcoin::util::hash::Sha256dHash;
use itertools::enumerate;
use daemon::Daemon;
use index::{compute_script_hash, HeaderEntry, Index, TxInKey, TxInRow, TxKey, TxOutRow};
use index::{compute_script_hash, HeaderEntry, Index, TxInRow, TxOutRow, TxRow};
use store::Store;
use types::{hash_prefix, HashPrefix, HASH_PREFIX_LEN};
use types::HashPrefix;
pub struct Query<'a> {
store: &'a Store,
@ -58,14 +57,17 @@ impl<'a> Query<'a> {
fn load_txns(&self, prefixes: Vec<HashPrefix>) -> Vec<TxnHeight> {
let mut txns = Vec::new();
for txid_prefix in prefixes {
for row in self.store.scan(&[b"T", &txid_prefix[..]].concat()) {
let key: TxKey = bincode::deserialize(&row.key).unwrap();
let txid: Sha256dHash = deserialize(&key.txid).unwrap();
let tx_rows: Vec<TxRow> = self.store
.scan(&TxRow::filter(&txid_prefix))
.iter()
.map(|row| TxRow::from_row(row))
.collect();
for tx_row in tx_rows {
let txid: Sha256dHash = deserialize(&tx_row.key.txid).unwrap();
let txn: Transaction = self.get_tx(&txid);
let height: u32 = bincode::deserialize(&row.value).unwrap();
txns.push(TxnHeight {
txn,
height: height as i32,
height: tx_row.height as i32,
})
}
}
@ -73,20 +75,11 @@ impl<'a> Query<'a> {
}
fn find_spending_input(&self, funding: &FundingOutput) -> Option<SpendingInput> {
let spend_key = bincode::serialize(&TxInKey {
code: b'I',
prev_hash_prefix: hash_prefix(&funding.txn_id[..]),
prev_index: funding.output_index as u16,
}).unwrap();
let spending_txns: Vec<TxnHeight> = self.load_txns(
self.store
.scan(&spend_key)
.scan(&TxInRow::filter(&funding.txn_id, funding.output_index))
.iter()
.map(|row| {
bincode::deserialize::<TxInRow>(&row.key)
.unwrap()
.txid_prefix
})
.map(|row| TxInRow::from_row(row).txid_prefix)
.collect(),
);
let mut spending_inputs = Vec::new();
@ -120,13 +113,9 @@ impl<'a> Query<'a> {
let funding_txns = self.load_txns(
self.store
.scan(&[b"O", &script_hash[..HASH_PREFIX_LEN]].concat())
.scan(&TxOutRow::filter(script_hash))
.iter()
.map(|row| {
bincode::deserialize::<TxOutRow>(&row.key)
.unwrap()
.txid_prefix
})
.map(|row| TxOutRow::from_row(row).txid_prefix)
.collect(),
);
for t in funding_txns {