Skip to content

Commit 3e24144

Browse files
authored
Merge pull request #46 from rustaceanrob/9-4-hints
Record offset in hintfile instead of literal index
2 parents 80e848e + 4e01288 commit 3e24144

8 files changed

Lines changed: 76 additions & 19 deletions

File tree

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,3 @@ This repository is a collection of crates related to a SwiftSync node implementa
77
- `accumulator`: A hash-based SwiftSync accumulator used to add and subtrack elements from a set.
88
- `hintfile`: Generate a SwiftSync hintfile as the role of a server.
99
- `node`: Perform fast IBD using a SwiftSync hints file.
10-
- `network`: Tools to find Bitcoin peers.

hintfile/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,13 @@ edition = "2021"
66
[dependencies]
77
kernel = { workspace = true }
88

9+
configure_me = "0.4.0"
10+
11+
[build-dependencies]
12+
configure_me_codegen = "0.4.0"
13+
14+
[package.metadata.configure_me]
15+
spec = "config_spec.toml"
16+
917
[[bin]]
1018
name = "construct"

hintfile/build.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
extern crate configure_me_codegen;
2+
3+
fn main() -> Result<(), configure_me_codegen::Error> {
4+
configure_me_codegen::build_script_auto()
5+
}

hintfile/config_spec.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[[param]]
2+
name = "name"
3+
type = "String"
4+
default = "\"./bitcoin.hints\".into()"
5+
doc = "The path to the .hints file you would like to create. Default is `./bitcoin.hints`"
6+
7+
[[param]]
8+
name = "bitcoin_dir"
9+
type = "String"
10+
default = "\"~/.bitcoin\".into()"
11+
doc = "The directory of your `bitcoind` data"
12+
13+
[[param]]
14+
name = "network"
15+
type = "String"
16+
default = "\"bitcoin\".into()"
17+
doc = "The bitcoin network to operate on. Default `bitcoin`. Options are `bitcoin` or `signet`"

hintfile/src/bin/construct.rs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,36 @@
1-
use std::{fs::File, io::Write, sync::Arc};
1+
use std::{fs::File, io::Write, path::PathBuf, str::FromStr};
22

33
use hintfile::write_compact_size;
44
use kernel::{ChainType, ChainstateManager, ChainstateManagerOptions, ContextBuilder, KernelError};
55

6-
const CHAIN_TYPE: ChainType = ChainType::SIGNET;
6+
configure_me::include_config!();
77

8-
fn main() {
9-
let mut file = File::create("./bitcoin.hints").unwrap();
8+
fn chain_type_from_string(network: String) -> ChainType {
9+
match network.to_lowercase().as_ref() {
10+
"bitcoin" => ChainType::MAINNET,
11+
"signet" => ChainType::SIGNET,
12+
_ => panic!("supported chains are `bitcoin` or `signet`"),
13+
}
14+
}
1015

11-
let mut args = std::env::args();
12-
let _ = args.next();
13-
let data_dir = args.next().expect("Usage: <path_to_bitcoin_dir>");
14-
let mut blocks_dir = data_dir.clone();
15-
blocks_dir.push_str("/blocks");
16+
fn main() {
17+
let (config, _) = Config::including_optional_config_files::<&[&str]>(&[]).unwrap_or_exit();
18+
let chain_type = chain_type_from_string(config.network);
19+
let hintfile_path = PathBuf::from_str(&config.name).unwrap();
20+
let bitcoind = PathBuf::from_str(&config.bitcoin_dir).unwrap();
21+
let blocks_dir = bitcoind.join("blocks");
22+
let mut file = File::create(hintfile_path).unwrap();
1623
println!("Initializing");
1724
let ctx = ContextBuilder::new()
18-
.chain_type(CHAIN_TYPE)
25+
.chain_type(chain_type)
1926
.build()
2027
.unwrap();
21-
let options = ChainstateManagerOptions::new(&ctx, &data_dir, &blocks_dir).unwrap();
22-
let _context = Arc::new(ctx);
28+
let options = ChainstateManagerOptions::new(
29+
&ctx,
30+
bitcoind.to_str().unwrap(),
31+
blocks_dir.to_str().unwrap(),
32+
)
33+
.unwrap();
2334
let chainman = ChainstateManager::new(options).unwrap();
2435
println!("Chain state initialized");
2536
// Writing the chain tip allows the client to know where to stop
@@ -39,6 +50,7 @@ fn main() {
3950
if chainman.have_coin(&transaction, vout) {
4051
println!("Found coin at offset {curr}");
4152
block_unspents.push(curr);
53+
curr = 0;
4254
}
4355
curr += 1;
4456
}

hintfile/src/lib.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,20 @@ impl Hints {
7979
///
8080
/// If there are no offset present at that height, aka an overflow, or the entry has already
8181
/// been fetched.
82-
pub fn get_block_offsets(&self, height: BlockHeight) -> Vec<u64> {
83-
self.map
82+
pub fn get_indexes(&self, height: BlockHeight) -> Vec<u64> {
83+
let offsets = self
84+
.map
8485
.get(&height)
8586
.cloned()
86-
.expect("block height overflow")
87+
.expect("block height overflow");
88+
let mut indexes = Vec::with_capacity(offsets.len());
89+
let mut prev = 0;
90+
for offset in offsets {
91+
let next = prev + offset;
92+
indexes.push(next);
93+
prev = next;
94+
}
95+
indexes
8796
}
8897
}
8998

node/src/bin/ibd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ fn main() {
7474
let acc_task = std::thread::spawn(move || accumulator_state.verify());
7575
let peers = Arc::new(Mutex::new(peers));
7676
let mut tasks = Vec::new();
77-
let hashes = hashes_from_chain(Arc::clone(&chain), task_num);
77+
let hashes = hashes_from_chain(Arc::clone(&chain), network, task_num);
7878
for (task_id, chunk) in hashes.into_iter().enumerate() {
7979
let chain = Arc::clone(&chain);
8080
let tx = tx.clone();

node/src/lib.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ pub fn get_blocks_for_range(
220220
.expect("header is in best chain.");
221221
let block_height = block_index.height().unsigned_abs();
222222
let unspent_indexes: HashSet<u64> =
223-
hints.get_block_offsets(block_height).into_iter().collect();
223+
hints.get_indexes(block_height).into_iter().collect();
224224
// tracing::info!("{task_id} -> {block_height}:{hash}");
225225
let file_path = block_dir.join(format!("{hash}.block"));
226226
let file = File::create_new(file_path);
@@ -315,7 +315,11 @@ pub fn get_blocks_for_range(
315315
tracing::info!("All block ranges fetched: {task_id}");
316316
}
317317

318-
pub fn hashes_from_chain(chain: Arc<ChainstateManager>, jobs: usize) -> Vec<Vec<BlockHash>> {
318+
pub fn hashes_from_chain(
319+
chain: Arc<ChainstateManager>,
320+
network: Network,
321+
jobs: usize,
322+
) -> Vec<Vec<BlockHash>> {
319323
let height = chain.best_header().height();
320324
let mut hashes = Vec::with_capacity(height as usize);
321325
let mut curr = chain.best_header();
@@ -330,6 +334,9 @@ pub fn hashes_from_chain(chain: Arc<ChainstateManager>, jobs: usize) -> Vec<Vec<
330334
hashes.push(hash);
331335
curr = next;
332336
}
337+
if matches!(network, Network::Signet) {
338+
return hashes.chunks(20_000).map(|slice| slice.to_vec()).collect();
339+
}
333340
// These blocks are empty. Fetch the maximum amount of blocks.
334341
let first_epoch = hashes.split_off(hashes.len() - 200_000);
335342
let first_chunks: Vec<Vec<BlockHash>> = first_epoch

0 commit comments

Comments
 (0)