diff --git a/hintfile/Cargo.toml b/hintfile/Cargo.toml index 0158f50..5f0f098 100644 --- a/hintfile/Cargo.toml +++ b/hintfile/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] bitcoin = { workspace = true } -kernel = { package = "bitcoinkernel", git = "https://github.com/alexanderwiederin/rust-bitcoinkernel.git", rev = "31a53ebc81cf3648de2adea3ef7ee62b7a993221" } +kernel = { package = "bitcoinkernel", git = "https://github.com/alexanderwiederin/rust-bitcoinkernel.git", rev = "b7b42d65a70f2c0e5fc8d1d024549bf857211046" } [[bin]] name = "construct" diff --git a/hintfile/src/bin/construct.rs b/hintfile/src/bin/construct.rs index ab02e5d..4205026 100644 --- a/hintfile/src/bin/construct.rs +++ b/hintfile/src/bin/construct.rs @@ -1,6 +1,5 @@ use std::{fs::File, io::Write, sync::Arc}; -use bitcoin::{consensus, OutPoint}; use hintfile::write_compact_size; use kernel::{ChainType, ChainstateManager, ChainstateManagerOptions, ContextBuilder, KernelError}; @@ -21,35 +20,32 @@ fn main() { let _context = Arc::new(ctx); let chainman = ChainstateManager::new(options).unwrap(); println!("Chain state initialized"); - let genesis = chainman.block_index_genesis(); + // Writing the chain tip allows the client to know where to stop let tip = chainman.block_index_tip().block_hash().hash; - file.write_all(&tip).unwrap(); + file.write_all(&tip).expect("file cannot be written to"); + + let genesis = chainman.block_index_genesis(); let mut current = chainman.next_block_index(genesis).unwrap(); loop { let block = chainman.read_block_data(¤t).unwrap(); - let bytes: Vec = block.into(); - let block = consensus::deserialize::(&bytes).unwrap(); - let (_, transactions) = block.into_parts(); - println!("On block {}", current.height()); - let mut delta: u64 = 0; - let mut block_offsets: Vec = Vec::new(); - for tx in transactions { - let txid = tx.compute_txid(); - for (index, _txout) in tx.outputs.iter().enumerate() { - let _outpoint = OutPoint { - txid, - vout: index as u32, - }; - // if true - block_offsets.push(delta); - delta = 0; + println!("Block {} ...", current.height()); + let mut block_unspents = Vec::new(); + let mut curr = 0; + for i in 0..block.transaction_count() { + let transaction = block.transaction(i).unwrap(); + for vout in 0..transaction.output_count() { + if chainman.have_coin(&transaction, vout) { + println!("Found coin at offset {curr}"); + block_unspents.push(curr); + } + curr += 1; } } + // Overflows 32 bit machines - let len_encode = block_offsets.len() as u64; - println!("Writing block offsets"); + let len_encode = block_unspents.len() as u64; write_compact_size(len_encode, &mut file).expect("unexpected EOF"); - for offset in block_offsets { + for offset in block_unspents { write_compact_size(offset, &mut file).expect("unexpected EOF"); } match chainman.next_block_index(current) { diff --git a/hintfile/src/lib.rs b/hintfile/src/lib.rs index 6015460..efb65d1 100644 --- a/hintfile/src/lib.rs +++ b/hintfile/src/lib.rs @@ -3,7 +3,7 @@ use std::{ io::{self, Read, Write}, }; -use bitcoin::{BlockHeight, BlockHeightInterval}; +use bitcoin::{consensus, BlockHash, BlockHeight, BlockHeightInterval}; pub fn write_compact_size(value: u64, writer: &mut W) -> Result<(), io::Error> { match value { @@ -45,6 +45,7 @@ pub fn read_compact_size(reader: &mut R) -> Result { #[derive(Debug)] pub struct Hints { map: BTreeMap>, + assume_valid: BlockHash, } impl Hints { @@ -54,6 +55,9 @@ impl Hints { pub fn from_file(reader: &mut R) -> Self { let mut map = BTreeMap::new(); let mut height = BlockHeight::from_u32(1); + let mut buf = [0; 32]; + reader.read_exact(&mut buf).expect("empty file"); + let assume_valid = consensus::deserialize::(&buf).expect("empty file."); while let Ok(count) = read_compact_size(reader) { // panics on 32 bit machines let mut offsets = Vec::with_capacity(count as usize); @@ -65,7 +69,12 @@ impl Hints { .checked_add(BlockHeightInterval::from_u32(1)) .expect("hintfile absurdly large.") } - Self { map } + Self { map, assume_valid } + } + + /// Get the last hash encoded in the hintfile. + pub fn stop_hash(&self) -> BlockHash { + self.assume_valid } /// # Panics