diff --git a/api/data.go b/api/data.go index dbf79069d..2953ffb3e 100644 --- a/api/data.go +++ b/api/data.go @@ -13,6 +13,7 @@ type EdgesProvider interface { GetEdges(ctx context.Context) ([]protocol.SpecEdge, error) GetEdge(ctx context.Context, hash common.Hash) (protocol.SpecEdge, error) GetHonestConfirmableEdges(ctx context.Context) (map[string][]protocol.SpecEdge, error) + GetEvilConfirmedEdges(ctx context.Context) ([]protocol.SpecEdge, error) ComputeHonestPathTimer(ctx context.Context, topLevelAssertionHash protocol.AssertionHash, edgeId protocol.EdgeId) (challengetree.PathTimer, challengetree.HonestAncestors, []challengetree.EdgeLocalTimer, error) } diff --git a/api/data_test.go b/api/data_test.go index 0e43f3b24..c2f63bf25 100644 --- a/api/data_test.go +++ b/api/data_test.go @@ -43,6 +43,10 @@ func (f *FakeEdgesProvider) GetHonestConfirmableEdges(ctx context.Context) (map[ return honestConfirmableEdges, nil } +func (f *FakeEdgesProvider) GetEvilConfirmedEdges(ctx context.Context) ([]protocol.SpecEdge, error) { + return f.Edges, nil +} + func (f *FakeEdgesProvider) ComputeHonestPathTimer(ctx context.Context, topLevelAssertionHash protocol.AssertionHash, edgeId protocol.EdgeId) (challengetree.PathTimer, challengetree.HonestAncestors, []challengetree.EdgeLocalTimer, error) { return 0, nil, nil, nil } diff --git a/api/method_edges.go b/api/method_edges.go index 1ad74c010..08ebb779d 100644 --- a/api/method_edges.go +++ b/api/method_edges.go @@ -16,7 +16,6 @@ func (s *Server) listHonestEdgesHandler(w http.ResponseWriter, r *http.Request) return } - // TODO: Allow params to sort by other fields sort.Slice(e, func(i, j int) bool { return e[i].CreatedAtBlock < e[j].CreatedAtBlock }) @@ -39,7 +38,6 @@ func (s *Server) listEdgesHandler(w http.ResponseWriter, r *http.Request) { return } - // TODO: Allow params to sort by other fields sort.Slice(e, func(i, j int) bool { return e[i].CreatedAtBlock < e[j].CreatedAtBlock }) @@ -71,6 +69,28 @@ func (s *Server) listHonestConfirmableEdgesHandler(w http.ResponseWriter, r *htt } } +func (s *Server) listEvilConfirmedEdgesHandler(w http.ResponseWriter, r *http.Request) { + confirmedEvilEdges, err := s.edges.GetEvilConfirmedEdges(r.Context()) + if err != nil { + writeError(w, http.StatusInternalServerError, err) + return + } + e, err := convertSpecEdgeEdgesToEdges(r.Context(), confirmedEvilEdges, s.edges) + if err != nil { + writeError(w, http.StatusInternalServerError, err) + return + } + + sort.Slice(e, func(i, j int) bool { + return e[i].CreatedAtBlock < e[j].CreatedAtBlock + }) + + if err := writeJSONResponse(w, 200, e); err != nil { + writeError(w, http.StatusInternalServerError, err) + return + } +} + func (s *Server) listMiniStakesHandler(w http.ResponseWriter, r *http.Request) { specEdges, err := s.edges.GetEdges(r.Context()) if err != nil { diff --git a/api/server.go b/api/server.go index 418b7ba08..3d44ffffd 100644 --- a/api/server.go +++ b/api/server.go @@ -99,6 +99,7 @@ func (s *Server) registerMethods() error { s.router.HandleFunc("/edges", s.listEdgesHandler).Methods("GET") s.router.HandleFunc("/edges/{id}", s.getEdgeHandler).Methods("GET") s.router.HandleFunc("/honest-confirmable-edges", s.listHonestConfirmableEdgesHandler).Methods("GET") + s.router.HandleFunc("/evil-confirmed-edges", s.listEvilConfirmedEdgesHandler).Methods("GET") // Stakes s.router.HandleFunc("/mini-stakes", s.listMiniStakesHandler).Methods("GET") diff --git a/challenge-manager/chain-watcher/watcher.go b/challenge-manager/chain-watcher/watcher.go index 166ac066b..8b0725408 100644 --- a/challenge-manager/chain-watcher/watcher.go +++ b/challenge-manager/chain-watcher/watcher.go @@ -564,6 +564,35 @@ func (w *Watcher) GetHonestConfirmableEdges(ctx context.Context) (map[string][]p return confirmableEdges, nil } +func (w *Watcher) GetEvilConfirmedEdges(ctx context.Context) ([]protocol.SpecEdge, error) { + edges, err := w.GetEdges(ctx) + if err != nil { + return nil, err + } + honestEdges := w.GetHonestEdges() + honestEdgesMap := make(map[common.Hash]protocol.SpecEdge) + for _, honestEdge := range honestEdges { + honestEdgesMap[honestEdge.Id().Hash] = honestEdge + } + evilEdges := make([]protocol.SpecEdge, 0) + for _, edge := range edges { + if _, ok := honestEdgesMap[edge.Id().Hash]; !ok { + evilEdges = append(evilEdges, edge) + } + } + evilConfirmedEdges := make([]protocol.SpecEdge, 0) + for _, evilEdge := range evilEdges { + status, err := evilEdge.Status(ctx) + if err != nil { + return nil, errors.Wrap(err, "could not get edge status") + } + if status == protocol.EdgeConfirmed { + evilConfirmedEdges = append(evilConfirmedEdges, evilEdge) + } + } + return evilConfirmedEdges, nil +} + // AddVerifiedHonestEdge adds an edge known to be honest to the chain watcher's internally // tracked challenge trees and spawns an edge tracker for it. Should be called after the challenge // manager creates a new edge, or bisects an edge and produces two children from that move.