From 1f608c9f2b7d04d1b713667df0780637f059f9f3 Mon Sep 17 00:00:00 2001 From: rustaceanrob Date: Tue, 11 Nov 2025 13:52:24 +0000 Subject: [PATCH] accumulator: Change to multiple rotating field elm When looking at the tools available in C++, the concept of "wrapping" does not come up. Instead of doing carries, the '+' operator silently wraps. If each outpoint is added and later spent, whether or not there is a carry should make no difference. --- accumulator/src/lib.rs | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/accumulator/src/lib.rs b/accumulator/src/lib.rs index ae07ef4..e2e87e5 100644 --- a/accumulator/src/lib.rs +++ b/accumulator/src/lib.rs @@ -54,15 +54,14 @@ impl Accumulator { // ref: https://github.com/rust-bitcoin/rust-bitcoin/blob/7bbb9085c63dc69e9da16ec9c11c698d6236c95c/bitcoin/src/pow.rs#L658 pub fn add(&mut self, outpoint: OutPoint) { let hash = hash_outpoint(outpoint); - let (big, little) = Self::create_rhs(hash); - let (high, low) = Self::add_internal(self.high, self.low, big, little); - *self = Self { high, low }; + self.add_hashed_outpoint(hash); } /// Add a pre-hashed outpoint to the accumulator. pub fn add_hashed_outpoint(&mut self, hash: [u8; 32]) { let (big, little) = Self::create_rhs(hash); - let (high, low) = Self::add_internal(self.high, self.low, big, little); + let high = self.high.wrapping_add(big); + let low = self.low.wrapping_add(little); *self = Self { high, low }; } @@ -77,36 +76,17 @@ impl Accumulator { /// Spend the inputs in a block by subtracing them from the accumulator. pub fn spend(&mut self, outpoint: OutPoint) { let hash = hash_outpoint(outpoint); - let (high, low) = Self::create_rhs(hash); - let high_inv = !high; - let low_inv = !low; - let (high, low) = Self::add_internal(self.high, self.low, high_inv, low_inv); - let (high, low) = Self::add_internal(high, low, 0, 1); - *self = Self { high, low } + self.spend_hashed_outpoint(hash); } /// Spend a pre-hashed outpoint from the accumulator. pub fn spend_hashed_outpoint(&mut self, hash: [u8; 32]) { - let (high, low) = Self::create_rhs(hash); - let high_inv = !high; - let low_inv = !low; - let (high, low) = Self::add_internal(self.high, self.low, high_inv, low_inv); - let (high, low) = Self::add_internal(high, low, 0, 1); + let (big, little) = Self::create_rhs(hash); + let high = self.high.wrapping_sub(big); + let low = self.low.wrapping_sub(little); *self = Self { high, low } } - // Add LHS to RHS, wrapping around if necessary - fn add_internal(lhs_high: u128, lhs_low: u128, rhs_high: u128, rhs_low: u128) -> (u128, u128) { - let high = lhs_high.wrapping_add(rhs_high); - let mut ret_high = high; - let (low, low_bits_overflow) = lhs_low.overflowing_add(rhs_low); - if low_bits_overflow { - // Carry - ret_high = ret_high.wrapping_add(1); - } - (ret_high, low) - } - fn create_rhs(hash: [u8; 32]) -> (u128, u128) { let (high, low) = split_in_half(hash); let big = u128::from_be_bytes(high);