Skip to content

Commit 8410301

Browse files
refactor(GuesserBuffer): Exfiltrate field mast_auth_paths
When switching to a new and improved block proposal, the MAST authentication paths used for guessing change, but (under the new consensus rule set) the remainder of the `GuesserBuffer` does not. This commit moves the field `mast_auth_paths` out of this struct and into the relevant functions' argument lists. As a result, the `GuesserBuffer` captures exactly that information that does not change between block proposals and can remain immutable. Co-authored-by: Thorkil Schmidiger <thor@neptune.cash>
1 parent 706d345 commit 8410301

File tree

6 files changed

+49
-30
lines changed

6 files changed

+49
-30
lines changed

neptune-core/src/application/loops/mine_loop.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ use crate::protocol::consensus::block::block_transaction::BlockTransaction;
4646
use crate::protocol::consensus::block::difficulty_control::difficulty_control;
4747
use crate::protocol::consensus::block::pow::GuesserBuffer;
4848
use crate::protocol::consensus::block::pow::Pow;
49+
use crate::protocol::consensus::block::pow::PowMastPaths;
4950
use crate::protocol::consensus::block::*;
5051
use crate::protocol::consensus::consensus_rule_set::ConsensusRuleSet;
5152
use crate::protocol::consensus::transaction::transaction_proof::TransactionProofType;
@@ -238,14 +239,15 @@ fn guess_worker(
238239
}
239240
info!("Completed: guess preprocessing.");
240241

242+
let mast_auth_paths = block.pow_mast_paths();
241243
let pool = ThreadPoolBuilder::new()
242244
.num_threads(threads_to_use)
243245
.build()
244246
.unwrap();
245247
let guess_result = pool.install(|| {
246248
rayon::iter::repeat(0)
247249
.map_init(rand::rng, |rng, _i| {
248-
guess_nonce_iteration(&guesser_buffer, threshold, rng, &sender)
250+
guess_nonce_iteration(&guesser_buffer, &mast_auth_paths, threshold, rng, &sender)
249251
})
250252
.find_any(|r| !r.block_not_found())
251253
.unwrap()
@@ -308,6 +310,7 @@ impl GuessNonceResult {
308310
#[inline]
309311
fn guess_nonce_iteration(
310312
guesser_buffer: &GuesserBuffer<{ BlockPow::MERKLE_TREE_HEIGHT }>,
313+
mast_auth_paths: &PowMastPaths,
311314
threshold: Digest,
312315
rng: &mut rand::rngs::ThreadRng,
313316
sender: &oneshot::Sender<NewBlockFound>,
@@ -320,7 +323,7 @@ fn guess_nonce_iteration(
320323
return GuessNonceResult::Cancelled;
321324
}
322325

323-
let result = Pow::guess(guesser_buffer, nonce, threshold);
326+
let result = Pow::guess(guesser_buffer, mast_auth_paths, nonce, threshold);
324327

325328
match result {
326329
Some(pow) => GuessNonceResult::NonceFound { pow: Box::new(pow) },
@@ -1067,6 +1070,7 @@ pub(crate) mod tests {
10671070
Some(target_block_interval),
10681071
network,
10691072
);
1073+
let mast_auth_paths = block.pow_mast_paths();
10701074
let threshold = previous_block.header().difficulty.target();
10711075
let num_iterations_launched = 1_000_000;
10721076
let tick = std::time::SystemTime::now();
@@ -1077,7 +1081,13 @@ pub(crate) mod tests {
10771081
let num_iterations_run =
10781082
rayon::iter::IntoParallelIterator::into_par_iter(0..num_iterations_launched)
10791083
.map_init(rand::rng, |prng, _i| {
1080-
guess_nonce_iteration(&guesser_buffer, threshold, prng, &worker_task_tx);
1084+
guess_nonce_iteration(
1085+
&guesser_buffer,
1086+
&mast_auth_paths,
1087+
threshold,
1088+
prng,
1089+
&worker_task_tx,
1090+
);
10811091
})
10821092
.count();
10831093
drop(worker_task_rx);
@@ -2140,9 +2150,10 @@ pub(crate) mod tests {
21402150

21412151
let guesser_buffer =
21422152
successor_block.guess_preprocess(None, None, ConsensusRuleSet::default());
2153+
let mast_auth_paths = successor_block.pow_mast_paths();
21432154
let target = predecessor_block.header().difficulty.target();
21442155
loop {
2145-
if BlockPow::guess(&guesser_buffer, rng.random(), target).is_some() {
2156+
if BlockPow::guess(&guesser_buffer, &mast_auth_paths, rng.random(), target).is_some() {
21462157
println!("found solution after {counter} guesses.");
21472158
break;
21482159
}

neptune-core/src/application/rpc/server.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5951,7 +5951,7 @@ mod tests {
59515951
);
59525952

59535953
let pow: BlockPow = random();
5954-
let resulting_block_hash = pow_puzzle.auth_paths.fast_mast_hash(pow);
5954+
let resulting_block_hash = pow_puzzle.pow_mast_paths.fast_mast_hash(pow);
59555955

59565956
block1.set_header_pow(pow);
59575957
block1.set_header_guesser_address(guesser_address.into());
@@ -5964,9 +5964,12 @@ mod tests {
59645964
// Check that succesful guess is accepted by endpoint.
59655965
let consensus_rule_set = ConsensusRuleSet::Reboot;
59665966
let guesser_buffer = block1.guess_preprocess(None, None, consensus_rule_set);
5967+
let mast_auth_paths = block1.pow_mast_paths();
59675968
let target = genesis.header().difficulty.target();
59685969
let valid_pow = loop {
5969-
if let Some(valid_pow) = Pow::guess(&guesser_buffer, random(), target) {
5970+
if let Some(valid_pow) =
5971+
Pow::guess(&guesser_buffer, &mast_auth_paths, random(), target)
5972+
{
59705973
break valid_pow;
59715974
}
59725975
};

neptune-core/src/application/rpc/server/proof_of_work_puzzle.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::Block;
1818
#[derive(Clone, Debug, Copy, Serialize, Deserialize)]
1919
pub struct ProofOfWorkPuzzle {
2020
// All fields public since used downstream by mining pool software.
21-
pub auth_paths: PowMastPaths,
21+
pub pow_mast_paths: PowMastPaths,
2222

2323
/// The threshold digest that defines when a PoW solution is valid. The
2424
/// block's hash must be less than or equal to this value.
@@ -53,7 +53,7 @@ impl ProofOfWorkPuzzle {
5353
let id = Tip5::hash(&auth_paths);
5454

5555
Self {
56-
auth_paths,
56+
pow_mast_paths: auth_paths,
5757
threshold,
5858
total_guesser_reward: guesser_reward,
5959
id,
@@ -67,16 +67,20 @@ impl ProofOfWorkPuzzle {
6767
pub fn solve(&self, consensus_rule_set: ConsensusRuleSet) -> BlockPow {
6868
use rayon::prelude::*;
6969
info!("Starting PoW preprocessing");
70-
let guesser_buffer =
71-
BlockPow::preprocess(self.auth_paths, None, consensus_rule_set, self.prev_block);
70+
let guesser_buffer = BlockPow::preprocess(
71+
self.pow_mast_paths,
72+
None,
73+
consensus_rule_set,
74+
self.prev_block,
75+
);
7276
info!("Done with PoW preprocessing");
7377

7478
info!("Now attempting to find valid nonce");
7579
let solution = (0u64..u64::MAX)
7680
.into_par_iter()
7781
.map(|i| {
7882
let nonce = Digest(bfe_array![0, 0, 0, 0, i]);
79-
BlockPow::guess(&guesser_buffer, nonce, self.threshold)
83+
BlockPow::guess(&guesser_buffer, &self.pow_mast_paths, nonce, self.threshold)
8084
})
8185
.find_map_any(|x| x)
8286
.expect("Should find solution within 2^{64} attempts");

neptune-core/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// enables nightly feature async_fn_track_caller for crate feature log-slow-write-lock.
66
// log-slow-write-lock logs warning when a write-lock is held longer than 100 millis.
77
// to enable: cargo +nightly build --features log-slow-write-lock
8-
#![cfg_attr(feature = "track-lock-location", feature(async_fn_track_caller))]
8+
// #![cfg_attr(feature = "track-lock-location", feature(async_fn_track_caller))]
99
//
1010
// If code coverage tool `cargo-llvm-cov` is running with the nightly toolchain,
1111
// enable the unstable “coverage” attribute. This allows using the annotation

neptune-core/src/protocol/consensus/block/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1305,14 +1305,17 @@ pub(crate) mod tests {
13051305
let network = Network::Main;
13061306
let genesis = Block::genesis(network);
13071307
let mut invalid_block = invalid_empty_block(&genesis, network);
1308+
let mast_auth_paths = invalid_block.pow_mast_paths();
13081309

13091310
for consensus_rule_set in ConsensusRuleSet::iter() {
13101311
let guesser_buffer = invalid_block.guess_preprocess(None, None, consensus_rule_set);
13111312
let target = Difficulty::from(2u32).target();
13121313
let mut rng = rng();
13131314

13141315
let valid_pow = loop {
1315-
if let Some(valid_pow) = Pow::guess(&guesser_buffer, rng.random(), target) {
1316+
if let Some(valid_pow) =
1317+
Pow::guess(&guesser_buffer, &mast_auth_paths, rng.random(), target)
1318+
{
13161319
break valid_pow;
13171320
}
13181321
};

neptune-core/src/protocol/consensus/block/pow.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,6 @@ pub struct GuesserBuffer<const MERKLE_TREE_HEIGHT: usize> {
278278

279279
hash: Digest,
280280

281-
/// Authentication paths for all fields but the PoW field
282-
mast_auth_paths: PowMastPaths,
283-
284281
/// The hash of the parent block of this guesser buffer.
285282
prev_block_digest: Digest,
286283
}
@@ -290,7 +287,6 @@ impl<const MERKLE_TREE_HEIGHT: usize> Default for GuesserBuffer<MERKLE_TREE_HEIG
290287
Self {
291288
merkle_tree: MTree::default(),
292289
hash: Default::default(),
293-
mast_auth_paths: Default::default(),
294290
prev_block_digest: Default::default(),
295291
}
296292
}
@@ -401,15 +397,15 @@ impl<const MERKLE_TREE_HEIGHT: usize> Pow<MERKLE_TREE_HEIGHT> {
401397
// iterate log-many times over the buffer to compute leafs from buds
402398
let mut outs = ins.clone();
403399
let mut buds = &mut ins;
404-
let mut leafs = &mut outs;
400+
let mut resulting_leafs = &mut outs;
405401
let mut num_swaps = 0;
406402
for i in 0..NUM_BUD_LAYERS {
407403
for j in 0..num_checkpoints {
408404
let range = (j * checkpoint_distance)..((j + 1) * checkpoint_distance);
409405
range
410406
.clone()
411407
.into_par_iter()
412-
.zip(leafs[range].par_iter_mut())
408+
.zip(resulting_leafs[range].par_iter_mut())
413409
.for_each(|(k, leaf)| {
414410
*leaf = Tip5::hash_pair(buds[k], buds[(k + (1 << i)) % Self::NUM_LEAFS]);
415411
});
@@ -418,11 +414,11 @@ impl<const MERKLE_TREE_HEIGHT: usize> Pow<MERKLE_TREE_HEIGHT> {
418414
return Default::default();
419415
}
420416
}
421-
std::mem::swap(&mut leafs, &mut buds);
417+
std::mem::swap(&mut resulting_leafs, &mut buds);
422418
num_swaps += 1;
423419
}
424420

425-
std::mem::swap(&mut leafs, &mut buds);
421+
std::mem::swap(&mut resulting_leafs, &mut buds);
426422
num_swaps += 1;
427423

428424
let (mut leafs, internal_nodes) = if num_swaps & 1 == 1 {
@@ -450,13 +446,13 @@ impl<const MERKLE_TREE_HEIGHT: usize> Pow<MERKLE_TREE_HEIGHT> {
450446
GuesserBuffer::<MERKLE_TREE_HEIGHT> {
451447
merkle_tree,
452448
hash,
453-
mast_auth_paths,
454449
prev_block_digest,
455450
}
456451
}
457452

458453
pub fn guess(
459454
buffer: &GuesserBuffer<MERKLE_TREE_HEIGHT>,
455+
mast_auth_paths: &PowMastPaths,
460456
nonce: Digest,
461457
target: Digest,
462458
) -> Option<Self> {
@@ -483,7 +479,7 @@ impl<const MERKLE_TREE_HEIGHT: usize> Pow<MERKLE_TREE_HEIGHT> {
483479
path_b,
484480
};
485481

486-
let pow_digest = buffer.mast_auth_paths.fast_mast_hash(pow);
482+
let pow_digest = mast_auth_paths.fast_mast_hash(pow);
487483
if pow_digest > target {
488484
None
489485
} else {
@@ -511,12 +507,14 @@ impl<const MERKLE_TREE_HEIGHT: usize> Pow<MERKLE_TREE_HEIGHT> {
511507
Self::leaf(leaf_prefix, index_b),
512508
)
513509
} else {
514-
let index_a =
515-
Self::bitreverse(index_a.try_into().unwrap(), Self::MERKLE_TREE_HEIGHT as u32)
516-
as u64;
517-
let index_b =
518-
Self::bitreverse(index_b.try_into().unwrap(), Self::MERKLE_TREE_HEIGHT as u32)
519-
as u64;
510+
let index_a = u64::from(Self::bitreverse(
511+
index_a.try_into().unwrap(),
512+
Self::MERKLE_TREE_HEIGHT as u32,
513+
));
514+
let index_b = u64::from(Self::bitreverse(
515+
index_b.try_into().unwrap(),
516+
Self::MERKLE_TREE_HEIGHT as u32,
517+
));
520518
(
521519
Self::leaf(leaf_prefix, index_a),
522520
Self::leaf(leaf_prefix, index_b),
@@ -691,7 +689,7 @@ pub(crate) mod tests {
691689
let mut successful_guess = None;
692690
'inner_loop: for _ in 0..120 {
693691
let nonce = rng.random();
694-
if let Some(solution) = Pow::guess(&buffer, nonce, target) {
692+
if let Some(solution) = Pow::guess(&buffer, &auth_paths, nonce, target) {
695693
successful_guess = Some(solution);
696694
break 'inner_loop;
697695
}

0 commit comments

Comments
 (0)