hermez-node/test/debugapi/debugapi.go
test/debugapi/debugapi.goRaw
1package debugapi
2
3import (
4 "context"
5 "net/http"
6 "time"
7
8 "github.com/gin-contrib/cors"
9 "github.com/gin-gonic/gin"
10 "github.com/hermeznetwork/hermez-node/common"
11 "github.com/hermeznetwork/hermez-node/db/statedb"
12 "github.com/hermeznetwork/hermez-node/log"
13)
14
15func handleNoRoute(c *gin.Context) {
16 c.JSON(http.StatusNotFound, gin.H{
17 "error": "404 page not found",
18 })
19}
20
21type errorMsg struct {
22 Message string
23}
24
25func badReq(err error, c *gin.Context) {
26 log.Errorw("Bad request", "err", err)
27 c.JSON(http.StatusBadRequest, errorMsg{
28 Message: err.Error(),
29 })
30}
31
32// DebugAPI is an http API with debugging endpoints
33type DebugAPI struct {
34 addr string
35 stateDB *statedb.StateDB // synchronizer statedb
36}
37
38// NewDebugAPI creates a new DebugAPI
39func NewDebugAPI(addr string, stateDB *statedb.StateDB) *DebugAPI {
40 return &DebugAPI{
41 stateDB: stateDB,
42 addr: addr,
43 }
44}
45
46func (a *DebugAPI) handleAccount(c *gin.Context) {
47 uri := struct {
48 Idx uint32
49 }{}
50 if err := c.ShouldBindUri(&uri); err != nil {
51 badReq(err, c)
52 return
53 }
54 account, err := a.stateDB.GetAccount(common.Idx(uri.Idx))
55 if err != nil {
56 badReq(err, c)
57 return
58 }
59 c.JSON(http.StatusOK, account)
60}
61
62func (a *DebugAPI) handleAccounts(c *gin.Context) {
63 accounts, err := a.stateDB.GetAccounts()
64 if err != nil {
65 badReq(err, c)
66 return
67 }
68 c.JSON(http.StatusOK, accounts)
69}
70
71func (a *DebugAPI) handleCurrentBatch(c *gin.Context) {
72 batchNum, err := a.stateDB.GetCurrentBatch()
73 if err != nil {
74 badReq(err, c)
75 return
76 }
77 c.JSON(http.StatusOK, batchNum)
78}
79
80func (a *DebugAPI) handleMTRoot(c *gin.Context) {
81 root := a.stateDB.MTGetRoot()
82 c.JSON(http.StatusOK, root)
83}
84
85// Run starts the http server of the DebugAPI. To stop it, pass a context with
86// cancelation (see `debugapi_test.go` for an example).
87func (a *DebugAPI) Run(ctx context.Context) error {
88 api := gin.Default()
89 api.NoRoute(handleNoRoute)
90 api.Use(cors.Default())
91 debugAPI := api.Group("/debug")
92
93 debugAPI.GET("sdb/batchnum", a.handleCurrentBatch)
94 debugAPI.GET("sdb/mtroot", a.handleMTRoot)
95 debugAPI.GET("sdb/accounts", a.handleAccounts)
96 debugAPI.GET("sdb/accounts/:Idx", a.handleAccount)
97
98 debugAPIServer := &http.Server{
99 Addr: a.addr,
100 Handler: api,
101 // Use some hardcoded numberes that are suitable for testing
102 ReadTimeout: 30 * time.Second, //nolint:gomnd
103 WriteTimeout: 30 * time.Second, //nolint:gomnd
104 MaxHeaderBytes: 1 << 20, //nolint:gomnd
105 }
106 go func() {
107 log.Infof("Debug API is ready at %v", a.addr)
108 if err := debugAPIServer.ListenAndServe(); err != nil &&
109 err != http.ErrServerClosed {
110 log.Fatalf("Listen: %s\n", err)
111 }
112 }()
113
114 <-ctx.Done()
115 log.Info("Stopping Debug API...")
116 if err := debugAPIServer.Shutdown(context.Background()); err != nil {
117 return err
118 }
119 log.Info("Debug API stopped")
120 return nil
121}