Skip to content

Commit 531262f

Browse files
authored
Merge pull request #65 from rustaceanrob/26-2-27-hintsfile
-
2 parents 8ffed55 + d6d7bd3 commit 531262f

File tree

8 files changed

+41
-126
lines changed

8 files changed

+41
-126
lines changed

aggregate/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,3 @@ bitcoin = { workspace = true }
88

99
[dev-dependencies]
1010
bitcoin = { workspace = true, default-features = true }
11-
rusqlite = { version = "0.36.0", features = ["bundled"] }

aggregate/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
# SwiftSync Accumulator
1+
# SwiftSync Aggregate
22

3-
This crate defines a simple accumulator that may add and spend `OutPoint` from a set. If the `OutPoint` are add and spent from the accumulator an equivalent number of times, the accumulator state is zero. Internally, the accumulator is represented as two `u128` integers. Hashing elements is far more computationally expensive than adding and subtracing from `u128` integers, so hashes may be pre-computed with functions in this crate.
3+
This create defines a simple aggregate that may add and spend `OutPoint` from a set. If the `OutPoint` are add and spent from the accumulator an equivalent number of times, the accumulator state is zero. Internally, the accumulator is represented as two `u128` integers. Hashing elements is far more computationally expensive than adding and subtracing from `u128` integers, so hashes may be pre-computed with functions in this create.

aggregate/src/lib.rs

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -107,63 +107,6 @@ impl Default for Aggregate {
107107
}
108108
}
109109

110-
const VOUT_MAX: usize = 16_000;
111-
112-
/// An alternative accumulator than that of the original SwiftSync write-up, intended to remove the
113-
/// hashes required to update elements in the set.
114-
#[derive(Debug)]
115-
pub struct MultAggregate {
116-
memo_table: [[[u8; 16]; 2]; VOUT_MAX],
117-
internal: u128,
118-
}
119-
120-
impl MultAggregate {
121-
pub fn new() -> Self {
122-
let mut memo_table = [[[0u8; 16]; 2]; VOUT_MAX];
123-
for (vout, arr) in memo_table.iter_mut().enumerate() {
124-
let bytes = sha256t::hash::<SwiftSyncTag>(&vout.to_le_bytes()).to_byte_array();
125-
let (left, right) = split_in_half(bytes);
126-
*arr = [left, right];
127-
}
128-
Self {
129-
memo_table,
130-
internal: 0,
131-
}
132-
}
133-
134-
fn compute_salted_value(&self, outpoint: OutPoint) -> u128 {
135-
let branches = self.memo_table[outpoint.vout as usize];
136-
let left = branches[0];
137-
let right = branches[1];
138-
let txid_bytes = outpoint.txid.to_byte_array();
139-
let (tx_left, tx_right) = split_in_half(txid_bytes);
140-
let lhs = u128::from_le_bytes(left).wrapping_mul(u128::from_le_bytes(tx_left));
141-
let rhs = u128::from_le_bytes(right).wrapping_mul(u128::from_le_bytes(tx_right));
142-
lhs.wrapping_add(rhs)
143-
}
144-
145-
/// Add an outpoint to the set
146-
pub fn add(&mut self, outpoint: OutPoint) {
147-
let salted_val = self.compute_salted_value(outpoint);
148-
self.internal = self.internal.wrapping_add(salted_val);
149-
}
150-
151-
/// Remove an outpoint from the set
152-
pub fn spend(&mut self, outpoint: OutPoint) {
153-
let salted_val = self.compute_salted_value(outpoint);
154-
self.internal = self.internal.wrapping_sub(salted_val);
155-
}
156-
157-
pub fn is_zero(&self) -> bool {
158-
self.internal.eq(&0)
159-
}
160-
}
161-
162-
impl Default for MultAggregate {
163-
fn default() -> Self {
164-
Self::new()
165-
}
166-
}
167110
#[cfg(test)]
168111
mod tests {
169112
use bitcoin::{
@@ -301,25 +244,4 @@ mod tests {
301244
acc.update(AggregateUpdate::Spent(hash_one));
302245
assert!(acc.is_zero());
303246
}
304-
305-
#[test]
306-
fn test_mult_agg_is_zero() {
307-
let mut acc = MultAggregate::default();
308-
let [outpoint_one, outpoint_two, outpoint_three, outpoint_four, outpoint_five] =
309-
make_five_outpoint();
310-
// Add the members
311-
acc.add(outpoint_one);
312-
acc.add(outpoint_two);
313-
acc.add(outpoint_five);
314-
acc.add(outpoint_four);
315-
acc.add(outpoint_three);
316-
assert!(!acc.is_zero());
317-
// Take away the members
318-
acc.spend(outpoint_two);
319-
acc.spend(outpoint_five);
320-
acc.spend(outpoint_three);
321-
acc.spend(outpoint_four);
322-
acc.spend(outpoint_one);
323-
assert!(acc.is_zero());
324-
}
325247
}

aggregate/tests/test.rs

Lines changed: 35 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,50 @@
1-
use aggregate::{Aggregate, MultAggregate};
1+
use aggregate::Aggregate;
22
use bitcoin::{OutPoint, Txid};
3-
use rusqlite::Connection;
43

5-
const SELECT_STMT: &str = "SELECT txid, vout FROM utxos";
4+
const TEST_ITERS: usize = 10_000;
5+
const TEST_SEED: u64 = 420;
66

7-
#[test]
8-
fn test_static_utxo_set() {
9-
let mut acc = Aggregate::new();
10-
let conn = Connection::open("../contrib/data/signet_outpoints.sqlite").unwrap();
11-
let mut stmt = conn.prepare(SELECT_STMT).unwrap();
12-
let mut rows = stmt.query([]).unwrap();
13-
while let Some(row) = rows.next().unwrap() {
14-
let txid: String = row.get(0).unwrap();
15-
let vout: u32 = row.get(1).unwrap();
16-
let txid = txid.parse::<Txid>().unwrap();
17-
let outpoint = OutPoint { txid, vout };
18-
acc.spend(outpoint);
7+
struct Rng {
8+
state: u64,
9+
}
10+
11+
impl Rng {
12+
fn new(seed: u64) -> Self {
13+
Rng {
14+
state: if seed == 0 { 1 } else { seed },
15+
}
1916
}
20-
assert!(!acc.is_zero());
21-
let mut stmt = conn.prepare(SELECT_STMT).unwrap();
22-
let mut rows = stmt.query([]).unwrap();
23-
while let Some(row) = rows.next().unwrap() {
24-
let txid: String = row.get(0).unwrap();
25-
let vout: u32 = row.get(1).unwrap();
26-
let txid = txid.parse::<Txid>().unwrap();
27-
let outpoint = OutPoint { txid, vout };
28-
acc.add(outpoint);
17+
18+
fn next_u64(&mut self) -> u64 {
19+
self.state ^= self.state << 13;
20+
self.state ^= self.state >> 7;
21+
self.state ^= self.state << 17;
22+
self.state
23+
}
24+
25+
fn next_32_bytes(&mut self) -> [u8; 32] {
26+
let mut out = [0u8; 32];
27+
for chunk in out.chunks_exact_mut(8) {
28+
chunk.copy_from_slice(&self.next_u64().to_le_bytes());
29+
}
30+
out
2931
}
30-
assert!(acc.is_zero());
3132
}
3233

3334
#[test]
34-
fn test_mult_agg() {
35-
let mut acc = MultAggregate::new();
36-
let conn = Connection::open("../contrib/data/signet_outpoints.sqlite").unwrap();
37-
let mut stmt = conn.prepare(SELECT_STMT).unwrap();
38-
let mut rows = stmt.query([]).unwrap();
39-
while let Some(row) = rows.next().unwrap() {
40-
let txid: String = row.get(0).unwrap();
41-
let vout: u32 = row.get(1).unwrap();
42-
let txid = txid.parse::<Txid>().unwrap();
35+
fn test_static_utxo_set() {
36+
let mut acc = Aggregate::new();
37+
let mut rng = Rng::new(TEST_SEED);
38+
let mut outpoints = Vec::with_capacity(TEST_ITERS);
39+
for _ in 0..TEST_ITERS {
40+
let txid = Txid::from_byte_array(rng.next_32_bytes());
41+
let vout = (rng.next_u64() % u32::MAX as u64) as u32;
4342
let outpoint = OutPoint { txid, vout };
4443
acc.spend(outpoint);
44+
outpoints.push(outpoint);
4545
}
4646
assert!(!acc.is_zero());
47-
let mut stmt = conn.prepare(SELECT_STMT).unwrap();
48-
let mut rows = stmt.query([]).unwrap();
49-
while let Some(row) = rows.next().unwrap() {
50-
let txid: String = row.get(0).unwrap();
51-
let vout: u32 = row.get(1).unwrap();
52-
let txid = txid.parse::<Txid>().unwrap();
53-
let outpoint = OutPoint { txid, vout };
47+
for outpoint in outpoints {
5448
acc.add(outpoint);
5549
}
5650
assert!(acc.is_zero());
-91 MB
Binary file not shown.

node/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SwiftSync fast IBD
22

3-
This binary implements a SwiftSync client that downloads blocks in parallel from multiple peers, references a hint file, and updates an accumulator. Once the client has reached the stop hash specified in the hint file, the accumulator state is reported as verified or false. For more information, read the [SwiftSync specification](https://gist.github.com/RubenSomsen/a61a37d14182ccd78760e477c78133cd).
3+
This binary implements a SwiftSync client that downloads blocks in parallel from multiple peers, references a hintsfile, and updates an accumulator. Once the client has reached the stop hash specified in the hintsfile, the accumulator state is reported as verified or false. For more information, read the [SwiftSync specification](https://gist.github.com/RubenSomsen/a61a37d14182ccd78760e477c78133cd).
44

55
You will need a `.hints` file locally to run this binary. You may download one from a server:
66

@@ -34,7 +34,7 @@ cargo run --bin ibd --release -- <args>
3434

3535
```
3636
Arguments:
37-
--hintfile The path to your `bitcoin.hints` file that will
37+
--hintsfile The path to your `bitcoin.hints` file that will
3838
be used for IBD. Default is `./bitcoin.hints`
3939
--blocks-dir Optional directory to store the blocks. Used
4040
only to measure performance.

node/config_spec.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[[param]]
2-
name = "hintfile"
2+
name = "hintsfile"
33
type = "String"
44
default = "\"./bitcoin.hints\".into()"
55
doc = "The path to your `bitcoin.hints` file that will be used for IBD. Default is `./bitcoin.hints`"

node/src/bin/ibd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ configure_me::include_config!();
2121

2222
fn main() {
2323
let (config, _) = Config::including_optional_config_files::<&[&str]>(&[]).unwrap_or_exit();
24-
let hint_path = config.hintfile;
24+
let hint_path = config.hintsfile;
2525
let blocks_dir = config.blocks_dir;
2626
let network = config
2727
.network

0 commit comments

Comments
 (0)