@@ -8,22 +8,26 @@ use concordium_rust_sdk::{
88 hashes:: BlockHash , queries:: BlockInfo , AbsoluteBlockHeight , BlockItemSummary ,
99 ContractAddress , SpecialTransactionOutcome ,
1010 } ,
11- v2:: { self , FinalizedBlockInfo } ,
11+ v2:: { self , FinalizedBlockInfo , Upward } ,
1212} ;
13- use futures:: TryStreamExt ;
13+ use futures:: { StreamExt , TryStreamExt } ;
1414use std:: { collections:: HashSet , convert:: TryFrom , hash:: Hash } ;
1515use structopt:: StructOpt ;
1616use tokio_postgres:: {
1717 types:: { Json , ToSql } ,
1818 Transaction as DBTransaction ,
1919} ;
2020use tonic:: async_trait;
21+ use tonic:: Status ;
2122use transaction_logger:: {
2223 postgres:: { self , DatabaseClient } ,
23- run_service, set_shutdown, BlockInsertSuccess , DatabaseError , DatabaseHooks , NodeError ,
24+ run_service, set_shutdown, BlockInsertSuccess , DatabaseHooks , IndexingError , NodeError ,
2425 NodeHooks , PrepareStatements , SharedIndexerArgs ,
2526} ;
2627
28+ type ContractEvents = Vec < cis2:: Event > ;
29+ type ContractEffects = Vec < ( ContractAddress , ContractEvents ) > ;
30+
2731type DBConn = transaction_logger:: DBConn < PreparedStatements > ;
2832
2933const MAX_CONNECT_ATTEMPTS : u32 = 6 ;
@@ -258,7 +262,7 @@ impl PreparedStatements {
258262 block_time : Timestamp ,
259263 block_height : AbsoluteBlockHeight ,
260264 ts : & BlockItemSummaryWithCanonicalAddresses ,
261- ) -> Result < ( ) , postgres :: Error > {
265+ ) -> Result < ( ) , IndexingError > {
262266 let affected_addresses = & ts. addresses ;
263267 let summary_row = SummaryRow {
264268 block_hash,
@@ -275,15 +279,27 @@ impl PreparedStatements {
275279 ] ;
276280 tx. query_opt ( & self . insert_ati , & values) . await ?;
277281 }
282+
278283 // insert contracts
279- for affected in ts. summary . affected_contracts ( ) {
284+ let affected_contracts = ts. summary . affected_contracts ( ) . known_or_else ( || {
285+ log:: error!( "Could not determine affected contracts for a BlockItemSummary of unknown type. {:?}" , ts. summary) ;
286+ IndexingError :: UnknownData ( "Could not determine affected contracts for a BlockItemSummary of unknown type." . to_string ( ) )
287+ } ) ?; // if Unknown, throw an error
288+
289+ for contract_address in affected_contracts {
290+ let affected = contract_address. known_or_else ( || {
291+ log:: error!( "Could not determine affected contracts of an unknown type of AccountTransactionEffects. {:?}" , ts. summary) ;
292+ IndexingError :: UnknownData ( "Could not determine affected contracts of an unknown type of AccountTransactionEffects." . to_string ( ) )
293+ } ) ?; // encountered unknown contract_address, throw an error, this will stop the insert into db process and alert the user to update the rust SDK
294+
280295 let index = affected. index ;
281296 let subindex = affected. subindex ;
282297 let values = [
283298 & ( index as i64 ) as & ( dyn ToSql + Sync ) ,
284299 & ( subindex as i64 ) ,
285300 & id,
286301 ] ;
302+
287303 tx. query_opt ( & self . insert_cti , & values) . await ?;
288304 }
289305
@@ -398,41 +414,41 @@ impl PreparedStatements {
398414 & self ,
399415 tx : & DBTransaction < ' _ > ,
400416 ts : & BlockItemSummary ,
401- ) -> Result < ( ) , postgres :: Error > {
402- if let Some ( effects) = get_cis2_events ( ts) {
403- for ( ca , events ) in effects {
404- for event in events {
405- match event {
406- cis2 :: Event :: Transfer { .. } => {
407- // do nothing, tokens are not created here.
408- }
409- cis2 :: Event :: Mint {
410- ref token_id ,
411- ref amount ,
412- ..
413- } => {
414- self . cis2_increase_total_supply ( tx , ca , token_id , amount )
415- . await ? ;
416- }
417- cis2 :: Event :: Burn {
418- ref token_id ,
419- ref amount ,
420- ..
421- } => {
422- self . cis2_decrease_total_supply ( tx , ca , token_id , amount )
423- . await ? ;
424- }
425- cis2 :: Event :: UpdateOperator { .. } => {
426- // do nothing, updating operators does not change
427- // token suply
428- }
429- cis2 :: Event :: TokenMetadata { .. } => {
430- // do nothing, updating token metadata does not
431- // change token supply.
432- }
433- cis2 :: Event :: Unknown => {
434- // do nothing, not a CIS2 event
435- }
417+ ) -> Result < ( ) , IndexingError > {
418+ let effects = get_cis2_events ( ts) ? ;
419+
420+ for ( ca , events ) in effects {
421+ for event in events {
422+ match event {
423+ cis2 :: Event :: Transfer { .. } => {
424+ // do nothing, tokens are not created here.
425+ }
426+ cis2 :: Event :: Mint {
427+ ref token_id ,
428+ ref amount ,
429+ ..
430+ } => {
431+ self . cis2_increase_total_supply ( tx , ca , token_id , amount )
432+ . await ? ;
433+ }
434+ cis2 :: Event :: Burn {
435+ ref token_id ,
436+ ref amount ,
437+ ..
438+ } => {
439+ self . cis2_decrease_total_supply ( tx , ca , token_id , amount )
440+ . await ? ;
441+ }
442+ cis2 :: Event :: UpdateOperator { .. } => {
443+ // do nothing, updating operators does not change
444+ // token suply
445+ }
446+ cis2 :: Event :: TokenMetadata { .. } => {
447+ // do nothing, updating token metadata does not
448+ // change token supply.
449+ }
450+ cis2 :: Event :: Unknown => {
451+ // do nothing, not a CIS2 event
436452 }
437453 }
438454 }
@@ -450,7 +466,7 @@ async fn insert_block(
450466 block_height : AbsoluteBlockHeight ,
451467 item_summaries : & [ BlockItemSummaryWithCanonicalAddresses ] ,
452468 special_events : & [ SpecialTransactionOutcome ] ,
453- ) -> Result < chrono:: Duration , postgres :: Error > {
469+ ) -> Result < chrono:: Duration , IndexingError > {
454470 let start = chrono:: Utc :: now ( ) ;
455471 let db_tx = db. client . as_mut ( ) . transaction ( ) . await ?;
456472 let prepared = & db. prepared ;
@@ -492,33 +508,55 @@ async fn get_last_block_height(
492508/// parsing then the logs for that section of execution are ignored, since it
493509/// indicates an error in the contract.
494510///
495- /// The return value of [`None`] means there are no understandable CIS2 logs
511+ /// The return value of empty vec means there are no understandable CIS2 logs
496512/// produced.
497- fn get_cis2_events ( bi : & BlockItemSummary ) -> Option < Vec < ( ContractAddress , Vec < cis2 :: Event > ) > > {
513+ fn get_cis2_events ( bi : & BlockItemSummary ) -> Result < ContractEffects , IndexingError > {
498514 match bi. contract_update_logs ( ) {
499- Some ( log_iter) => Some (
500- log_iter
501- . flat_map ( |( ca, logs) | {
502- match logs
503- . iter ( )
504- . map ( cis2:: Event :: try_from)
505- . collect :: < Result < Vec < cis2:: Event > , _ > > ( )
506- {
507- Ok ( events) => Some ( ( ca, events) ) ,
508- Err ( _) => None ,
509- }
510- } )
511- . collect ( ) ,
512- ) ,
515+ Some ( log_iter) => {
516+ // Map each log into a Result
517+ let mut events: ContractEffects = Vec :: new ( ) ;
518+ for contract_log in log_iter {
519+ let ( ca, logs) = contract_log. known_or_else ( || {
520+ log:: error!(
521+ "Could not determine contract log, unknown type. {:?}" ,
522+ contract_log
523+ ) ;
524+ IndexingError :: UnknownData (
525+ "Could not determine contract log, unknown type." . to_string ( ) ,
526+ )
527+ } ) ?;
528+
529+ let evs = logs
530+ . iter ( )
531+ . map ( cis2:: Event :: try_from)
532+ . collect :: < Result < Vec < cis2:: Event > , _ > > ( )
533+ . ok ( ) ;
534+
535+ if let Some ( evs) = evs {
536+ events. push ( ( ca, evs) ) ;
537+ }
538+ }
539+ //if no events were parsed due to non cis2 logs, the vector will be empty
540+ //so just return the events vector, empty or not empty.
541+ Ok ( events)
542+ }
513543 None => {
514- let init = bi. contract_init ( ) ?;
515- let cis2 = init
544+ let init = match bi. contract_init ( ) {
545+ Some ( init) => init,
546+ None => return Ok ( vec ! [ ] ) ,
547+ } ;
548+
549+ let cis2 = match init
516550 . events
517551 . iter ( )
518552 . map ( cis2:: Event :: try_from)
519553 . collect :: < Result < Vec < cis2:: Event > , _ > > ( )
520- . ok ( ) ?;
521- Some ( vec ! [ ( init. address, cis2) ] )
554+ {
555+ Ok ( vec) => vec,
556+ Err ( _) => return Ok ( vec ! [ ] ) ,
557+ } ;
558+
559+ Ok ( vec ! [ ( init. address, cis2) ] )
522560 }
523561 }
524562}
@@ -531,7 +569,7 @@ impl DatabaseHooks<TransactionLogData, PreparedStatements> for DatabaseState {
531569 async fn insert_into_db (
532570 db_conn : & mut DBConn ,
533571 ( bi, item_summaries, special_events) : & TransactionLogData ,
534- ) -> Result < BlockInsertSuccess , DatabaseError > {
572+ ) -> Result < BlockInsertSuccess , IndexingError > {
535573 let duration = insert_block (
536574 db_conn,
537575 bi. block_hash ,
@@ -551,7 +589,7 @@ impl DatabaseHooks<TransactionLogData, PreparedStatements> for DatabaseState {
551589
552590 async fn on_request_max_height (
553591 db : & DatabaseClient ,
554- ) -> Result < Option < AbsoluteBlockHeight > , DatabaseError > {
592+ ) -> Result < Option < AbsoluteBlockHeight > , IndexingError > {
555593 let height = get_last_block_height ( db) . await ?;
556594 Ok ( height)
557595 }
@@ -602,18 +640,30 @@ impl NodeHooks<TransactionLogData> for CanonicalAddressCache {
602640 . try_collect ( )
603641 . await ?
604642 } ;
643+
605644 let special_events = node
606645 . get_block_special_events ( finalized_block_info. height )
607646 . await ?
608647 . response
648+ . map ( |upward_res| {
649+ upward_res. and_then ( |upward| match upward {
650+ Upward :: Known ( special_transaction_outcome) => Ok ( special_transaction_outcome) ,
651+ Upward :: Unknown => {
652+ Err ( Status :: unknown ( "Unknown SpecialTransactionOutcome type" ) )
653+ }
654+ } )
655+ } )
609656 . try_collect ( )
610657 . await ?;
611658
612659 // Map account addresses affected by each summary to their respective canonical
613660 // address
614661 let mut with_addresses = Vec :: with_capacity ( transaction_summaries. len ( ) ) ;
615662 for summary in transaction_summaries {
616- let affected_addresses = summary. affected_addresses ( ) ;
663+ let affected_addresses = summary. affected_addresses ( ) . known_or_else ( || {
664+ Status :: unknown ( "Could not determine affected addresses for BlockItem" )
665+ } ) ?; // if unknown, throw Err Status::unknown
666+
617667 let mut addresses = Vec :: with_capacity ( affected_addresses. len ( ) ) ;
618668 // resolve canonical addresses. This part is only needed because the index
619669 // is currently expected by "canonical address",
0 commit comments