diff --git a/data/repo/transaction.go b/data/repo/transaction.go index 3bcf9d3..ba1ebbb 100644 --- a/data/repo/transaction.go +++ b/data/repo/transaction.go @@ -100,3 +100,24 @@ func (r *transactionRepo) FindRunningAndCreatedBeforeThreshold(tx *gorm.DB, date } return transactions, nil } + +func (r *transactionRepo) FindTimeTakenToWeakness(tx *gorm.DB, taskId string, weaknessType common.OracleType) (uint32, error) { + var totalTimeInSeconds uint32 + query := ` + SELECT + strftime('%s', timestamp) - strftime('%s', ( + SELECT MIN(timestamp) + FROM transactions + WHERE task_id = ?) + ) + FROM transactions + WHERE detected_weaknesses like ? + ORDER BY timestamp + LIMIT 1 + ` + + if err := tx.Raw(query, taskId, "%"+weaknessType+"%").Scan(&totalTimeInSeconds).Error; err != nil { + return 0, err + } + return totalTimeInSeconds, nil +} diff --git a/listener/reporter.go b/listener/reporter.go index 5f53ed0..ee5f708 100644 --- a/listener/reporter.go +++ b/listener/reporter.go @@ -72,6 +72,7 @@ func (l *reporterListener) processEvent(ctx context.Context, evt bus.TaskFinishE heatmap := l.initHeatMap(contract.CFG) aggregatedWeakneses := make([]string, 0) + timeToWeaknessMap := make(map[string]uint32) var totalCoverage float64 = 0 var averageCoverage float64 = 0 var criticalInstructionsHits uint64 = 0 @@ -89,6 +90,15 @@ func (l *reporterListener) processEvent(ctx context.Context, evt bus.TaskFinishE averageCoverage = totalCoverage / float64(len(transactions)) } + detectedWeaknesses := common.GetUniqueSlice(aggregatedWeakneses) + for _, weakness := range detectedWeaknesses { + timeToWeakness, err := l.transactionService.FindTimeTakenToWeakness(task.Id, common.OracleType(weakness)) + if err != nil { + l.logger.Sugar().Errorf("an error occurred when retrieving transactions of this task: %v", err) + } + timeToWeaknessMap[weakness] = timeToWeakness + } + report := common.TaskReport{ TaskId: task.Id, TaskStatus: task.Status, @@ -100,6 +110,7 @@ func (l *reporterListener) processEvent(ctx context.Context, evt bus.TaskFinishE MinDistance: distance.ComputeMinDistance(contract.DistanceMap, task.AggregatedExecutedInstructions), MinDistanceByTime: l.computeMinDistanceByTime(contract.DistanceMap, transactions), DetectedWeaknesses: common.GetUniqueSlice(aggregatedWeakneses), + TimeToWeakness: timeToWeaknessMap, CriticalInstructionsHits: criticalInstructionsHits, AverageCoverage: averageCoverage, Instructions: l.buildInstructionsMap(contract.CFG), diff --git a/pkg/common/types.go b/pkg/common/types.go index 54c427a..08d6145 100644 --- a/pkg/common/types.go +++ b/pkg/common/types.go @@ -92,6 +92,7 @@ type TaskReport struct { MinDistance uint64 `json:"minDistance"` MinDistanceByTime TimeSeriesData `json:"minDistanceByTime"` DetectedWeaknesses []string `json:"detectedWeaknesses"` + TimeToWeakness map[string]uint32 `json:"timeToWeaknesses"` CriticalInstructionsHits uint64 `json:"criticalInstructionsHits"` AverageCoverage float64 `json:"averageCoverage"` Instructions map[string]string `json:"instructions"` diff --git a/pkg/interfaces/repo.go b/pkg/interfaces/repo.go index c1b8f39..c187683 100644 --- a/pkg/interfaces/repo.go +++ b/pkg/interfaces/repo.go @@ -4,6 +4,7 @@ import ( "time" "github.com/dogefuzz/dogefuzz/entities" + "github.com/dogefuzz/dogefuzz/pkg/common" "gorm.io/gorm" ) @@ -41,4 +42,5 @@ type TransactionRepo interface { FindDoneByTaskId(tx *gorm.DB, taskId string) ([]entities.Transaction, error) FindDoneTransactionsByFunctionIdAndOrderByTimestamp(tx *gorm.DB, functionId string, limit int64) ([]entities.Transaction, error) FindRunningAndCreatedBeforeThreshold(tx *gorm.DB, dateThreshold time.Time) ([]entities.Transaction, error) + FindTimeTakenToWeakness(tx *gorm.DB, taskId string, weaknessType common.OracleType) (uint32, error) } diff --git a/pkg/interfaces/service.go b/pkg/interfaces/service.go index 2f0a9b5..dc7d95a 100644 --- a/pkg/interfaces/service.go +++ b/pkg/interfaces/service.go @@ -55,6 +55,7 @@ type TransactionService interface { FindDoneByTaskId(taskId string) ([]*dto.TransactionDTO, error) FindDoneTransactionsByFunctionIdAndOrderByTimestamp(functionId string, limit int64) ([]*dto.TransactionDTO, error) FindRunningAndCreatedBeforeThreshold(dateThreshold time.Time) ([]*dto.TransactionDTO, error) + FindTimeTakenToWeakness(taskId string, weaknessType common.OracleType) (uint32, error) } type VandalService interface { diff --git a/service/transaction.go b/service/transaction.go index 078b3fa..44a12d3 100644 --- a/service/transaction.go +++ b/service/transaction.go @@ -6,6 +6,7 @@ import ( "time" "github.com/dogefuzz/dogefuzz/data/repo" + "github.com/dogefuzz/dogefuzz/pkg/common" "github.com/dogefuzz/dogefuzz/pkg/dto" "github.com/dogefuzz/dogefuzz/pkg/interfaces" ) @@ -157,3 +158,12 @@ func (s *transactionService) FindRunningAndCreatedBeforeThreshold(dateThreshold } return transactionDTOs, nil } + +func (s *transactionService) FindTimeTakenToWeakness(taskId string, weaknessType common.OracleType) (uint32, error) { + timeToWeakness, err := s.transactionRepo.FindTimeTakenToWeakness(s.connection.GetDB(), taskId, weaknessType) + if err != nil { + return 0, err + } + return timeToWeakness, nil + +}