eureka-network / rs-eureka

Eureka sink
0 stars 0 forks source link

Steps for event filtering #105

Open jorgeantonio21 opened 1 year ago

jorgeantonio21 commented 1 year ago

After a long discussion with @benjaminbollen we arrived at the following steps (which are not necessarily definite or correct, currently), to generate a full circuit that guarantees that block events are actually retrieved correct and that filtering over a fixed address provides the correct subset of events with that same address:

let event_root_commitment_targets = builder.add_virtual_hash();
let event_address_targets = builder.add_virtual_targets(5);
let event_targets = builder.add_virtual_targets(event.len());
let mut leaves_event_hash_targets = vec![];
for event_targets in all_event_targets {
  // event_targets is of vec![Target; 5];
  let hashed_targets = builder.hash_or_noop(event_targets)
}

...

// now connect the leaves together in a tree
let mut final_height = false
while !final_height {
  // hash siblings
  let parent_hashed_targets = builder.hash_or_noop(left_hash_sibling_targets, right_hash_sibling_targets);
  ...
}

// when having the final root, connect it to the to the merkle root targets 'attached' to `C_n`:
for i in 0..4 {
  builder.connect(event_root_commitment_targets[i], computed_event_root_targets[i]);
}
  for each (event, event_targets) in events.iter().zip(all_events_targets) {
    let event_address = event.address;
    let event_address_targets = builder.add_virtual_targets(5); // each address has length 5
    // connect each event address targets to the correct event_targets
    // this ensures that event address targets correspond well to the range 
    // in the event target
    for i in 0..5 {
      builder.connect(event_address_targets[i], event_targets[2 + i]);
    }

    // continue by filtering events according to the fixed address
    ...
  }
for (index, event) in events.enumerate() {
  event_targets = {
     let event_index_target = builder.add_virtual_target(builder.constant(F::from_canonical_u64(index)));
     let event_targets = builder.add_virtual_targets(event.len() + 1);
     // store event targets in `all_event_targets
     // connect the first target with `event_index_target`
     builder.connect(event_index_target, event_targets[0]);
  };

WARNING: If following this approach, do not hash the first index target to generate the Merkle root (on the builder), see point 2.

// loop over every selected event, i.e., events whose address matches that of the original one 
for event_targets in selected_all_event_targets {
  let index = builder.target_as_constant(event_targets[0]).to_canonical_u64();
  builder.connect(all_event_targets[index as usize], selected_all_event_targets[index as usize]); // ignore cast math overflow issues for now 
}

If we follow this approach we need to verify that indexes are well formed:

for (index, event_targets) in all_event_targets.enumerate() {
    builder.connect(builder._true, builder.is_equal(event_targets[0], builder.constand(F::from_canonical_u64(index));
}