Skip to content

Commit a944e19

Browse files
committed
Implement hintfile creation
Use `have_coin` on the chain state manager to determine if a block offset should be written to. The block offset now encodes the literal index in a block. I will compress later if this is too large.
1 parent 0d3f75c commit a944e19

File tree

3 files changed

+29
-25
lines changed

3 files changed

+29
-25
lines changed

hintfile/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ edition = "2021"
55

66
[dependencies]
77
bitcoin = { workspace = true }
8-
kernel = { package = "bitcoinkernel", git = "https://github.com/alexanderwiederin/rust-bitcoinkernel.git", rev = "31a53ebc81cf3648de2adea3ef7ee62b7a993221" }
8+
kernel = { package = "bitcoinkernel", git = "https://github.com/alexanderwiederin/rust-bitcoinkernel.git", rev = "dfe8a59af3b9e26c1efa8e12e03b81373d14c76a" }
99

1010
[[bin]]
1111
name = "construct"

hintfile/src/bin/construct.rs

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::{fs::File, io::Write, sync::Arc};
22

3-
use bitcoin::{consensus, OutPoint};
43
use hintfile::write_compact_size;
54
use kernel::{ChainType, ChainstateManager, ChainstateManagerOptions, ContextBuilder, KernelError};
65

@@ -21,35 +20,31 @@ fn main() {
2120
let _context = Arc::new(ctx);
2221
let chainman = ChainstateManager::new(options).unwrap();
2322
println!("Chain state initialized");
24-
let genesis = chainman.block_index_genesis();
23+
// Writing the chain tip allows the client to know where to stop
2524
let tip = chainman.block_index_tip().block_hash().hash;
26-
file.write_all(&tip).unwrap();
25+
file.write_all(&tip).expect("file cannot be written to");
26+
27+
let genesis = chainman.block_index_genesis();
2728
let mut current = chainman.next_block_index(genesis).unwrap();
2829
loop {
2930
let block = chainman.read_block_data(&current).unwrap();
30-
let bytes: Vec<u8> = block.into();
31-
let block = consensus::deserialize::<bitcoin::Block>(&bytes).unwrap();
32-
let (_, transactions) = block.into_parts();
33-
println!("On block {}", current.height());
34-
let mut delta: u64 = 0;
35-
let mut block_offsets: Vec<u64> = Vec::new();
36-
for tx in transactions {
37-
let txid = tx.compute_txid();
38-
for (index, _txout) in tx.outputs.iter().enumerate() {
39-
let _outpoint = OutPoint {
40-
txid,
41-
vout: index as u32,
42-
};
43-
// if true
44-
block_offsets.push(delta);
45-
delta = 0;
31+
println!("Block {} ...", current.height());
32+
let mut block_unspents = Vec::new();
33+
let mut curr = 0;
34+
for i in 0..block.transaction_count() {
35+
let transaction = block.transaction(i).unwrap();
36+
for vout in 0..transaction.output_count() {
37+
if chainman.have_coin(&transaction, vout) {
38+
block_unspents.push(curr);
39+
}
40+
curr += 1;
4641
}
4742
}
43+
4844
// Overflows 32 bit machines
49-
let len_encode = block_offsets.len() as u64;
50-
println!("Writing block offsets");
45+
let len_encode = block_unspents.len() as u64;
5146
write_compact_size(len_encode, &mut file).expect("unexpected EOF");
52-
for offset in block_offsets {
47+
for offset in block_unspents {
5348
write_compact_size(offset, &mut file).expect("unexpected EOF");
5449
}
5550
match chainman.next_block_index(current) {

hintfile/src/lib.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::{
33
io::{self, Read, Write},
44
};
55

6-
use bitcoin::{BlockHeight, BlockHeightInterval};
6+
use bitcoin::{consensus, BlockHash, BlockHeight, BlockHeightInterval};
77

88
pub fn write_compact_size<W: Write>(value: u64, writer: &mut W) -> Result<(), io::Error> {
99
match value {
@@ -45,6 +45,7 @@ pub fn read_compact_size<R: Read>(reader: &mut R) -> Result<u64, io::Error> {
4545
#[derive(Debug)]
4646
pub struct Hints {
4747
map: BTreeMap<BlockHeight, Vec<u64>>,
48+
assume_valid: BlockHash,
4849
}
4950

5051
impl Hints {
@@ -54,6 +55,9 @@ impl Hints {
5455
pub fn from_file<R: Read>(reader: &mut R) -> Self {
5556
let mut map = BTreeMap::new();
5657
let mut height = BlockHeight::from_u32(1);
58+
let mut buf = [0; 32];
59+
reader.read_exact(&mut buf).expect("empty file");
60+
let assume_valid = consensus::deserialize::<BlockHash>(&buf).expect("empty file.");
5761
while let Ok(count) = read_compact_size(reader) {
5862
// panics on 32 bit machines
5963
let mut offsets = Vec::with_capacity(count as usize);
@@ -65,7 +69,12 @@ impl Hints {
6569
.checked_add(BlockHeightInterval::from_u32(1))
6670
.expect("hintfile absurdly large.")
6771
}
68-
Self { map }
72+
Self { map, assume_valid }
73+
}
74+
75+
/// Get the last hash encoded in the hintfile.
76+
pub fn stop_hash(&self) -> BlockHash {
77+
self.assume_valid
6978
}
7079

7180
/// # Panics

0 commit comments

Comments
 (0)