mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
Add mock proof server
This commit is contained in:
47
test/proofserver/cli/main.go
Normal file
47
test/proofserver/cli/main.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hermeznetwork/hermez-node/test/proofserver"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var addr string
|
||||
flag.StringVar(&addr, "a", "localhost:3000", "listen address")
|
||||
var provingDuration time.Duration
|
||||
flag.DurationVar(&provingDuration, "d", 2*time.Second, "proving time duration") //nolint:gomnd
|
||||
flag.Parse()
|
||||
|
||||
mock := proofserver.NewMock(addr, provingDuration)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
if err := mock.Run(ctx); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
stopCh := make(chan interface{})
|
||||
// catch ^C to send the stop signal
|
||||
ossig := make(chan os.Signal, 1)
|
||||
signal.Notify(ossig, os.Interrupt)
|
||||
go func() {
|
||||
for sig := range ossig {
|
||||
if sig == os.Interrupt {
|
||||
stopCh <- nil
|
||||
}
|
||||
}
|
||||
}()
|
||||
<-stopCh
|
||||
cancel()
|
||||
wg.Wait()
|
||||
}
|
||||
191
test/proofserver/proofserver.go
Normal file
191
test/proofserver/proofserver.go
Normal file
@@ -0,0 +1,191 @@
|
||||
package proofserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gin-contrib/cors"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/hermeznetwork/hermez-node/log"
|
||||
"github.com/hermeznetwork/hermez-node/prover"
|
||||
"github.com/hermeznetwork/tracerr"
|
||||
)
|
||||
|
||||
type msg struct {
|
||||
value string
|
||||
ackCh chan bool
|
||||
}
|
||||
|
||||
func newMsg(value string) msg {
|
||||
return msg{
|
||||
value: value,
|
||||
ackCh: make(chan bool),
|
||||
}
|
||||
}
|
||||
|
||||
// Mock proof server
|
||||
type Mock struct {
|
||||
addr string
|
||||
status prover.StatusCode
|
||||
sync.RWMutex
|
||||
proof string
|
||||
pubData string
|
||||
counter int
|
||||
msgCh chan msg
|
||||
wg sync.WaitGroup
|
||||
provingDuration time.Duration
|
||||
}
|
||||
|
||||
// NewMock creates a new mock server
|
||||
func NewMock(addr string, provingDuration time.Duration) *Mock {
|
||||
return &Mock{
|
||||
addr: addr,
|
||||
status: prover.StatusCodeReady,
|
||||
proof: "",
|
||||
pubData: "",
|
||||
counter: 0,
|
||||
msgCh: make(chan msg),
|
||||
provingDuration: provingDuration,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Mock) err(c *gin.Context, err error) {
|
||||
c.JSON(http.StatusInternalServerError, prover.ErrorServer{
|
||||
Status: "error",
|
||||
Message: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Mock) handleCancel(c *gin.Context) {
|
||||
msg := newMsg("cancel")
|
||||
s.msgCh <- msg
|
||||
<-msg.ackCh
|
||||
c.JSON(http.StatusOK, "OK")
|
||||
}
|
||||
|
||||
func (s *Mock) handleStatus(c *gin.Context) {
|
||||
s.RLock()
|
||||
c.JSON(http.StatusOK, prover.Status{
|
||||
Status: s.status,
|
||||
Proof: s.proof,
|
||||
PubData: s.pubData,
|
||||
})
|
||||
s.RUnlock()
|
||||
}
|
||||
|
||||
func (s *Mock) handleInput(c *gin.Context) {
|
||||
s.RLock()
|
||||
if !s.status.IsReady() {
|
||||
s.err(c, fmt.Errorf("not ready"))
|
||||
s.RUnlock()
|
||||
return
|
||||
}
|
||||
s.RUnlock()
|
||||
_, err := ioutil.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
s.err(c, err)
|
||||
return
|
||||
}
|
||||
msg := newMsg("prove")
|
||||
s.msgCh <- msg
|
||||
<-msg.ackCh
|
||||
c.JSON(http.StatusOK, "OK")
|
||||
}
|
||||
|
||||
const longWaitDuration = 999 * time.Hour
|
||||
|
||||
// const provingDuration = 2 * time.Second
|
||||
|
||||
func (s *Mock) runProver(ctx context.Context) {
|
||||
waitDuration := longWaitDuration
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case msg := <-s.msgCh:
|
||||
switch msg.value {
|
||||
case "cancel":
|
||||
waitDuration = longWaitDuration
|
||||
s.Lock()
|
||||
if !s.status.IsReady() {
|
||||
s.status = prover.StatusCodeAborted
|
||||
}
|
||||
s.Unlock()
|
||||
case "prove":
|
||||
waitDuration = s.provingDuration
|
||||
s.Lock()
|
||||
s.status = prover.StatusCodeBusy
|
||||
s.Unlock()
|
||||
}
|
||||
msg.ackCh <- true
|
||||
case <-time.After(waitDuration):
|
||||
waitDuration = longWaitDuration
|
||||
s.Lock()
|
||||
if s.status != prover.StatusCodeBusy {
|
||||
s.Unlock()
|
||||
continue
|
||||
}
|
||||
i := s.counter * 100 //nolint:gomnd
|
||||
s.counter++
|
||||
// Mock data
|
||||
s.proof = fmt.Sprintf(`{
|
||||
"pi_a": ["%v", "%v"],
|
||||
"pi_b": [["%v", "%v"],["%v", "%v"],["%v", "%v"]],
|
||||
"pi_c": ["%v", "%v"],
|
||||
"protocol": "groth16"
|
||||
}`, i, i+1, i+2, i+3, i+4, i+5, i+6, i+7, i+8, i+9) //nolint:gomnd
|
||||
s.pubData = fmt.Sprintf(`[
|
||||
"%v"
|
||||
]`, i+42) //nolint:gomnd
|
||||
s.status = prover.StatusCodeSuccess
|
||||
s.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run the mock server. Use ctx to stop it via cancel
|
||||
func (s *Mock) Run(ctx context.Context) error {
|
||||
api := gin.Default()
|
||||
api.Use(cors.Default())
|
||||
|
||||
apiGroup := api.Group("/api")
|
||||
apiGroup.GET("/status", s.handleStatus)
|
||||
apiGroup.POST("/input", s.handleInput)
|
||||
apiGroup.POST("/cancel", s.handleCancel)
|
||||
|
||||
debugAPIServer := &http.Server{
|
||||
Addr: s.addr,
|
||||
Handler: api,
|
||||
// Use some hardcoded numberes that are suitable for testing
|
||||
ReadTimeout: 30 * time.Second, //nolint:gomnd
|
||||
WriteTimeout: 30 * time.Second, //nolint:gomnd
|
||||
MaxHeaderBytes: 1 << 20, //nolint:gomnd
|
||||
}
|
||||
go func() {
|
||||
log.Infof("prover.MockServer is ready at %v", s.addr)
|
||||
if err := debugAPIServer.ListenAndServe(); err != nil && tracerr.Unwrap(err) != http.ErrServerClosed {
|
||||
log.Fatalf("Listen: %s\n", err)
|
||||
}
|
||||
}()
|
||||
s.wg.Add(1)
|
||||
go func() {
|
||||
s.runProver(ctx)
|
||||
s.wg.Done()
|
||||
}()
|
||||
|
||||
<-ctx.Done()
|
||||
log.Info("Stopping prover.MockServer...")
|
||||
|
||||
s.wg.Wait()
|
||||
ctxTimeout, cancel := context.WithTimeout(context.Background(), 10*time.Second) //nolint:gomnd
|
||||
defer cancel()
|
||||
if err := debugAPIServer.Shutdown(ctxTimeout); err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
log.Info("prover.MockServer done")
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user