@@ -6,6 +6,7 @@ use std::{
66use anyhow:: { anyhow, Context as _} ;
77use ceramic_core:: { EventId , Network , StreamId } ;
88use ceramic_event:: unvalidated:: { self , signed:: cacao:: Capability } ;
9+ use ceramic_validation:: { event_verifier:: Verifier , AtTime , VerifyJwsOpts } ;
910use cid:: Cid ;
1011use futures:: TryStreamExt ;
1112use ipld_core:: ipld:: Ipld ;
@@ -26,6 +27,10 @@ pub struct Migrator<'a, S> {
2627 blocks : S ,
2728 batch : Vec < ReconItem < EventId > > ,
2829 log_tile_docs : bool ,
30+ // set of sep values to import, if an event doesn't have these values it will be skipped.
31+ sep_filter : Vec < Vec < u8 > > ,
32+ validate_signatures : bool ,
33+ supported_chains : Option < Vec < String > > ,
2934
3035 // All unsigned init payloads we have found.
3136 unsigned_init_payloads : BTreeSet < Cid > ,
@@ -48,12 +53,18 @@ impl<'a, S: BlockStore> Migrator<'a, S> {
4853 network : Network ,
4954 blocks : S ,
5055 log_tile_docs : bool ,
56+ sep_filter : Vec < Vec < u8 > > ,
57+ validate_signatures : bool ,
58+ supported_chains : Option < Vec < String > > ,
5159 ) -> Result < Self > {
5260 Ok ( Self {
5361 network,
5462 service,
5563 blocks,
5664 log_tile_docs,
65+ sep_filter,
66+ validate_signatures,
67+ supported_chains,
5768 batch : Default :: default ( ) ,
5869 unsigned_init_payloads : Default :: default ( ) ,
5970 referenced_unsigned_init_payloads : Default :: default ( ) ,
@@ -71,7 +82,7 @@ impl<'a, S: BlockStore> Migrator<'a, S> {
7182 Err ( Error :: MissingBlock ( * cid) )
7283 }
7384 }
74- fn handle_error ( & mut self , cid : Cid , err : & Error ) {
85+ fn handle_error ( & mut self , cid : Cid , err : & Error , model_context : ModelContext ) {
7586 let log = match err {
7687 Error :: FoundInitTileDoc ( _) | Error :: FoundDataTileDoc ( _) => {
7788 self . tile_doc_count += 1 ;
@@ -86,12 +97,12 @@ impl<'a, S: BlockStore> Migrator<'a, S> {
8697 . entry ( model. to_owned ( ) )
8798 . and_modify ( |count| * count += 1 )
8899 . or_insert ( 1 ) ;
89- self . handle_error ( cid, err) ;
100+ self . handle_error ( cid, err, model . clone ( ) ) ;
90101 false
91102 }
92103 } ;
93104 if log {
94- error ! ( %cid, err=format!( "{err:#}" ) , "error processing block" ) ;
105+ error ! ( %cid, err=format!( "{err:#}" ) , model=%model_context , "error processing block" ) ;
95106 }
96107 }
97108
@@ -105,7 +116,7 @@ impl<'a, S: BlockStore> Migrator<'a, S> {
105116 while let Some ( ( cid, data) ) = all_blocks. try_next ( ) . await ? {
106117 let ret = self . process_block ( cid, & data) . await ;
107118 if let Err ( err) = ret {
108- self . handle_error ( cid, & err)
119+ self . handle_error ( cid, & err, ModelContext ( None ) )
109120 }
110121 if self . batch . len ( ) > 1000 {
111122 if let Err ( err) = self . write_batch ( ) . await {
@@ -208,12 +219,8 @@ impl<'a, S: BlockStore> Migrator<'a, S> {
208219 ) ;
209220 let event = unvalidated:: init:: Event :: new ( payload) ;
210221 let event: unvalidated:: Event < Ipld > = unvalidated:: Event :: from ( Box :: new ( event) ) ;
211- self . batch . push (
212- event_builder
213- . build ( & self . network , event)
214- . await
215- . with_model_context ( & model) ?,
216- ) ;
222+ self . validate_build_and_push ( event_builder, event, & model)
223+ . await ?;
217224 if self . batch . len ( ) > 1000 {
218225 self . write_batch ( ) . await ?
219226 }
@@ -296,13 +303,8 @@ impl<'a, S: BlockStore> Migrator<'a, S> {
296303 }
297304 let s = unvalidated:: signed:: Event :: new ( cid, event, link, payload, capability) ;
298305 let event = unvalidated:: Event :: from ( s) ;
299- self . batch . push (
300- event_builder
301- . build ( & self . network , event)
302- . await
303- . with_model_context ( & model) ?,
304- ) ;
305- Ok ( ( ) )
306+ self . validate_build_and_push ( event_builder, event, & model)
307+ . await
306308 }
307309 fn is_tile_doc_init ( & self , data : & [ u8 ] ) -> bool {
308310 // Attempt to decode the payload as a loose TileDocument.
@@ -427,12 +429,51 @@ impl<'a, S: BlockStore> Migrator<'a, S> {
427429 }
428430 let time = unvalidated:: TimeEvent :: new ( event, proof, proof_edges) ;
429431 let event: unvalidated:: Event < Ipld > = unvalidated:: Event :: from ( Box :: new ( time) ) ;
430- self . batch . push (
431- event_builder
432- . build ( & self . network , event)
433- . await
434- . with_model_context ( & model) ?,
435- ) ;
432+ self . validate_build_and_push ( event_builder, event, & model)
433+ . await
434+ }
435+
436+ // Build the event and push onto the batch if its is valid.
437+ async fn validate_build_and_push (
438+ & mut self ,
439+ event_builder : EventBuilder ,
440+ event : unvalidated:: Event < Ipld > ,
441+ model : & ModelContext ,
442+ ) -> Result < ( ) > {
443+ if self . sep_filter . is_empty ( ) || self . sep_filter . contains ( & event_builder. sep ) {
444+ match & event {
445+ unvalidated:: Event :: Time ( event) => {
446+ if let Some ( supported_chains) = & self . supported_chains {
447+ let chain_id = event. proof ( ) . chain_id ( ) . to_owned ( ) ;
448+ if !supported_chains. contains ( & chain_id) {
449+ return Err ( anyhow ! ( "event has unsupported chain: {chain_id}" ) )
450+ . with_model_context ( model) ;
451+ }
452+ }
453+ }
454+ unvalidated:: Event :: Signed ( event) => {
455+ if self . validate_signatures {
456+ event
457+ . verify_signature (
458+ Some ( & event_builder. controller ) ,
459+ & VerifyJwsOpts {
460+ at_time : AtTime :: SkipTimeChecks ,
461+ ..Default :: default ( )
462+ } ,
463+ )
464+ . await
465+ . with_model_context ( model) ?;
466+ }
467+ }
468+ unvalidated:: Event :: Unsigned ( _) => { }
469+ } ;
470+ self . batch . push (
471+ event_builder
472+ . build ( & self . network , event)
473+ . await
474+ . with_model_context ( model) ?,
475+ ) ;
476+ }
436477 Ok ( ( ) )
437478 }
438479}
0 commit comments