@@ -127,6 +127,63 @@ impl Default for Accumulator {
127127 }
128128}
129129
130+ const VOUT_MAX : usize = 16_000 ;
131+
132+ /// An alternative accumulator than that of the original SwiftSync write-up, intended to remove the
133+ /// hashes required to update elements in the set.
134+ #[ derive( Debug ) ]
135+ pub struct MultAggregate {
136+ memo_table : [ [ [ u8 ; 16 ] ; 2 ] ; VOUT_MAX ] ,
137+ internal : u128 ,
138+ }
139+
140+ impl MultAggregate {
141+ pub fn new ( ) -> Self {
142+ let mut memo_table = [ [ [ 0u8 ; 16 ] ; 2 ] ; VOUT_MAX ] ;
143+ for ( vout, arr) in memo_table. iter_mut ( ) . enumerate ( ) {
144+ let bytes = sha256t:: hash :: < SwiftSyncTag > ( & vout. to_le_bytes ( ) ) . to_byte_array ( ) ;
145+ let ( left, right) = split_in_half ( bytes) ;
146+ * arr = [ left, right] ;
147+ }
148+ Self {
149+ memo_table,
150+ internal : 0 ,
151+ }
152+ }
153+
154+ fn compute_salted_value ( & self , outpoint : OutPoint ) -> u128 {
155+ let branches = self . memo_table [ outpoint. vout as usize ] ;
156+ let left = branches[ 0 ] ;
157+ let right = branches[ 1 ] ;
158+ let txid_bytes = outpoint. txid . to_byte_array ( ) ;
159+ let ( tx_left, tx_right) = split_in_half ( txid_bytes) ;
160+ let lhs = u128:: from_le_bytes ( left) . wrapping_mul ( u128:: from_le_bytes ( tx_left) ) ;
161+ let rhs = u128:: from_le_bytes ( right) . wrapping_mul ( u128:: from_le_bytes ( tx_right) ) ;
162+ lhs. wrapping_add ( rhs)
163+ }
164+
165+ /// Add an outpoint to the set
166+ pub fn add ( & mut self , outpoint : OutPoint ) {
167+ let salted_val = self . compute_salted_value ( outpoint) ;
168+ self . internal = self . internal . wrapping_add ( salted_val) ;
169+ }
170+
171+ /// Remove an outpoint from the set
172+ pub fn spend ( & mut self , outpoint : OutPoint ) {
173+ let salted_val = self . compute_salted_value ( outpoint) ;
174+ self . internal = self . internal . wrapping_sub ( salted_val) ;
175+ }
176+
177+ pub fn is_zero ( & self ) -> bool {
178+ self . internal . eq ( & 0 )
179+ }
180+ }
181+
182+ impl Default for MultAggregate {
183+ fn default ( ) -> Self {
184+ Self :: new ( )
185+ }
186+ }
130187#[ cfg( test) ]
131188mod tests {
132189 use bitcoin:: {
@@ -264,4 +321,25 @@ mod tests {
264321 acc. update ( AccumulatorUpdate :: Spent ( hash_one) ) ;
265322 assert ! ( acc. is_zero( ) ) ;
266323 }
324+
325+ #[ test]
326+ fn test_mult_agg_is_zero ( ) {
327+ let mut acc = MultAggregate :: default ( ) ;
328+ let [ outpoint_one, outpoint_two, outpoint_three, outpoint_four, outpoint_five] =
329+ make_five_outpoint ( ) ;
330+ // Add the members
331+ acc. add ( outpoint_one) ;
332+ acc. add ( outpoint_two) ;
333+ acc. add ( outpoint_five) ;
334+ acc. add ( outpoint_four) ;
335+ acc. add ( outpoint_three) ;
336+ assert ! ( !acc. is_zero( ) ) ;
337+ // Take away the members
338+ acc. spend ( outpoint_two) ;
339+ acc. spend ( outpoint_five) ;
340+ acc. spend ( outpoint_three) ;
341+ acc. spend ( outpoint_four) ;
342+ acc. spend ( outpoint_one) ;
343+ assert ! ( acc. is_zero( ) ) ;
344+ }
267345}
0 commit comments