diff --git a/neptune-core/src/application/loops/main_loop/proof_upgrader.rs b/neptune-core/src/application/loops/main_loop/proof_upgrader.rs index 333498e84..fdf11e138 100644 --- a/neptune-core/src/application/loops/main_loop/proof_upgrader.rs +++ b/neptune-core/src/application/loops/main_loop/proof_upgrader.rs @@ -255,7 +255,17 @@ impl UpgradeJob { TxProvingCapability::PrimitiveWitness => { panic!("Client cannot have primitive witness capability only") } - TxProvingCapability::LockScript => todo!("TODO: Add support for this"), + TxProvingCapability::LockScript if network.use_mock_proof() => { + UpgradeJob::PrimitiveWitnessToSingleProof(PrimitiveWitnessToSingleProof { + primitive_witness, + }) + } + TxProvingCapability::LockScript => { + panic!( + "Client cannot upgrade primitive witness with lock-script-only proving capability; use \ + --tx-proving-capability=proofcollection or singleproof to broadcast transactions" + ) + } } } diff --git a/neptune-core/src/application/loops/sync_loop/synchronization_bit_mask.rs b/neptune-core/src/application/loops/sync_loop/synchronization_bit_mask.rs index 651333f0e..5c78528ef 100644 --- a/neptune-core/src/application/loops/sync_loop/synchronization_bit_mask.rs +++ b/neptune-core/src/application/loops/sync_loop/synchronization_bit_mask.rs @@ -149,10 +149,31 @@ impl SynchronizationBitMask { /// put it into canonical representation. Canonical representation means /// the `lower_bound` field points to the first zero. fn canonize(mut self) -> SynchronizationBitMask { - // TODO: very slow. improve perf! - while self.contains(self.lower_bound) { - self.lower_bound += 1; - if self.lower_bound.is_multiple_of(32) { + while self.lower_bound < self.upper_bound && self.contains(self.lower_bound) { + if self.limbs.is_empty() { + break; + } + let rel = (self.lower_bound % 32) as u32; + let first = self.limbs[0]; + let max_bits_in_limb = u64::from(32 - rel); + let remaining = self.upper_bound - self.lower_bound; + let chunk = max_bits_in_limb.min(remaining); + let chunk_u32 = u32::try_from(chunk).expect("chunk fits in u32"); + let mask = if chunk_u32 == 32 { + u32::MAX + } else { + (1u32 << chunk_u32) - 1 + }; + let shifted = first >> rel; + let run = u64::from((shifted & mask).trailing_ones()); + if run == 0 { + break; + } + let advance = run.min(remaining); + let old_lb = self.lower_bound; + self.lower_bound += advance; + let boundaries_crossed = (self.lower_bound / 32).saturating_sub(old_lb / 32); + for _ in 0..boundaries_crossed { self.limbs.pop_front(); } } diff --git a/neptune-core/src/state/transaction/tx_proving_capability.rs b/neptune-core/src/state/transaction/tx_proving_capability.rs index b32863be1..328b0349b 100644 --- a/neptune-core/src/state/transaction/tx_proving_capability.rs +++ b/neptune-core/src/state/transaction/tx_proving_capability.rs @@ -28,7 +28,9 @@ impl From for TransactionProofType { fn from(c: TxProvingCapability) -> Self { match c { TxProvingCapability::PrimitiveWitness => Self::PrimitiveWitness, - TxProvingCapability::LockScript => unimplemented!(), + // No distinct proof type: lock-script capability proves the same + // on-chain primitive-witness shape; prover jobs still use PW type. + TxProvingCapability::LockScript => Self::PrimitiveWitness, TxProvingCapability::ProofCollection => Self::ProofCollection, TxProvingCapability::SingleProof => Self::SingleProof, } @@ -93,6 +95,15 @@ impl rand::distr::Distribution for rand::distr::StandardUni #[cfg(test)] mod tests { use super::*; + use crate::protocol::consensus::transaction::transaction_proof::TransactionProofType; + + #[test] + fn lockscript_maps_to_primitive_witness_proof_type() { + assert_eq!( + TransactionProofType::PrimitiveWitness, + TxProvingCapability::LockScript.into() + ); + } #[test] fn can_prove_simple() {