mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 11:26:44 +01:00
Update prover & add test
This commit is contained in:
28
prover/README.md
Normal file
28
prover/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
## Test Prover
|
||||
|
||||
### Server Proof API
|
||||
It is necessary to have a docker with server locally.
|
||||
|
||||
The instructions in the following link can be followed:
|
||||
https://github.com/hermeznetwork/test-info/tree/main/cli-prover
|
||||
|
||||
> It is necessary to consult the pre-requirements to follow the steps of the next summary
|
||||
|
||||
A summary of the steps to follow to run docker would be:
|
||||
|
||||
- Clone the repository: https://github.com/hermeznetwork/test-info
|
||||
- `cd cli-prover`
|
||||
- `./cli-prover.sh -s localhost -v ~/prover_data -r 22`
|
||||
- To enter docker: `docker exec -ti docker_cusnarks bash`
|
||||
- Inside the docker: `cd cusnarks; make docker_all FORCE_CPU=1`
|
||||
- Inside the docker: `cd config; python3 cusnarks_config.py 22 BN256`
|
||||
- To exit docker: `exit`
|
||||
- Now, the server API can be used. Helper can be consulted with: `./cli-prover.sh -h`
|
||||
- Is necessary to initialize the server with: `./cli-prover.sh --post-start <session>`
|
||||
- When `./cli-prover.sh --get-status <session>` is `ready` can be run the test.
|
||||
|
||||
> The session can be consulted with `tmux ls`. The session will be the number of the last session on the list.
|
||||
|
||||
### Test
|
||||
|
||||
`INTEGRATION=1 go test`
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
@@ -13,18 +14,21 @@ import (
|
||||
|
||||
"github.com/dghubble/sling"
|
||||
"github.com/hermeznetwork/hermez-node/common"
|
||||
"github.com/hermeznetwork/hermez-node/log"
|
||||
"github.com/hermeznetwork/tracerr"
|
||||
)
|
||||
|
||||
// Proof TBD this type will be received from the proof server
|
||||
type Proof struct {
|
||||
PiA []string `json:"pi_a"`
|
||||
PiB [][]string `json:"pi_b"`
|
||||
PiC []string `json:"pi_c"`
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
// Client is the interface to a ServerProof that calculates zk proofs
|
||||
type Client interface {
|
||||
// Non-blocking
|
||||
CalculateProof(zkInputs *common.ZKInputs) error
|
||||
CalculateProof(ctx context.Context, zkInputs *common.ZKInputs) error
|
||||
// Blocking
|
||||
GetProof(ctx context.Context) (*Proof, error)
|
||||
// Non-Blocking
|
||||
@@ -105,23 +109,22 @@ const (
|
||||
GET apiMethod = "GET"
|
||||
// POST is an HTTP POST with maybe JSON body
|
||||
POST apiMethod = "POST"
|
||||
// POSTFILE is an HTTP POST with a form file
|
||||
POSTFILE apiMethod = "POSTFILE"
|
||||
)
|
||||
|
||||
// ProofServerClient contains the data related to a ProofServerClient
|
||||
type ProofServerClient struct {
|
||||
URL string
|
||||
client *sling.Sling
|
||||
timeCons time.Duration
|
||||
}
|
||||
|
||||
// NewProofServerClient creates a new ServerProof
|
||||
func NewProofServerClient(URL string) *ProofServerClient {
|
||||
func NewProofServerClient(URL string, timeCons time.Duration) *ProofServerClient {
|
||||
if URL[len(URL)-1] != '/' {
|
||||
URL += "/"
|
||||
}
|
||||
client := sling.New().Base(URL)
|
||||
return &ProofServerClient{URL: URL, client: client}
|
||||
return &ProofServerClient{URL: URL, client: client, timeCons: timeCons}
|
||||
}
|
||||
|
||||
//nolint:unused
|
||||
@@ -170,15 +173,6 @@ func (p *ProofServerClient) apiRequest(ctx context.Context, method apiMethod, pa
|
||||
req, err = p.client.New().Get(path).Request()
|
||||
case POST:
|
||||
req, err = p.client.New().Post(path).BodyJSON(body).Request()
|
||||
case POSTFILE:
|
||||
provider, err := newFormFileProvider(body)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
req, err = p.client.New().Post(path).BodyProvider(provider).Request()
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
default:
|
||||
return tracerr.Wrap(fmt.Errorf("invalid http method: %v", method))
|
||||
}
|
||||
@@ -215,7 +209,7 @@ func (p *ProofServerClient) apiCancel(ctx context.Context) error {
|
||||
|
||||
//nolint:unused
|
||||
func (p *ProofServerClient) apiInput(ctx context.Context, zkInputs *common.ZKInputs) error {
|
||||
if err := p.apiRequest(ctx, POSTFILE, "/input", zkInputs, nil); err != nil {
|
||||
if err := p.apiRequest(ctx, POST, "/input", zkInputs, nil); err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
return nil
|
||||
@@ -223,28 +217,70 @@ func (p *ProofServerClient) apiInput(ctx context.Context, zkInputs *common.ZKInp
|
||||
|
||||
// CalculateProof sends the *common.ZKInputs to the ServerProof to compute the
|
||||
// Proof
|
||||
func (p *ProofServerClient) CalculateProof(zkInputs *common.ZKInputs) error {
|
||||
log.Error("TODO")
|
||||
return tracerr.Wrap(common.ErrTODO)
|
||||
func (p *ProofServerClient) CalculateProof(ctx context.Context, zkInputs *common.ZKInputs) error {
|
||||
err := p.apiInput(ctx, zkInputs)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetProof retreives the Proof from the ServerProof, blocking until the proof
|
||||
// is ready.
|
||||
func (p *ProofServerClient) GetProof(ctx context.Context) (*Proof, error) {
|
||||
log.Error("TODO")
|
||||
return nil, tracerr.Wrap(common.ErrTODO)
|
||||
status, err := p.apiStatus(ctx)
|
||||
if err != nil {
|
||||
return nil, tracerr.Wrap(err)
|
||||
}
|
||||
if status.Status == StatusCodeSuccess {
|
||||
var proof Proof
|
||||
err := json.Unmarshal([]byte(status.Proof), &proof)
|
||||
if err != nil {
|
||||
return nil, tracerr.Wrap(err)
|
||||
}
|
||||
return &proof, nil
|
||||
} else {
|
||||
return nil, errors.New("State is not Success")
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel cancels any current proof computation
|
||||
func (p *ProofServerClient) Cancel(ctx context.Context) error {
|
||||
log.Error("TODO")
|
||||
return tracerr.Wrap(common.ErrTODO)
|
||||
err := p.apiCancel(ctx)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitReady waits until the serverProof is ready
|
||||
func (p *ProofServerClient) WaitReady(ctx context.Context) error {
|
||||
log.Error("TODO")
|
||||
return tracerr.Wrap(common.ErrTODO)
|
||||
status, err := p.apiStatus(ctx)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
if !status.Status.IsInitialized() {
|
||||
err := errors.New("Proof Server is not initialized")
|
||||
return err
|
||||
} else {
|
||||
if status.Status.IsReady() {
|
||||
return nil
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return tracerr.Wrap(common.ErrDone)
|
||||
case <-time.After(p.timeCons):
|
||||
status, err := p.apiStatus(ctx)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
if status.Status.IsReady() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MockClient is a mock ServerProof to be used in tests. It doesn't calculate anything
|
||||
|
||||
83
prover/prover_test.go
Normal file
83
prover/prover_test.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package prover
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hermeznetwork/hermez-node/common"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const apiURL = "http://localhost:3000/api"
|
||||
const timeCons = 1 * time.Second
|
||||
|
||||
var proofServerClient *ProofServerClient
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
exitVal := 0
|
||||
if os.Getenv("INTEGRATION") != "" {
|
||||
proofServerClient = NewProofServerClient(apiURL, timeCons)
|
||||
err := proofServerClient.WaitReady(context.Background())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
exitVal = m.Run()
|
||||
}
|
||||
os.Exit(exitVal)
|
||||
}
|
||||
|
||||
func TestApiServer(t *testing.T) {
|
||||
t.Run("testAPIStatus", testAPIStatus)
|
||||
t.Run("testCalculateProof", testCalculateProof)
|
||||
time.Sleep(time.Second / 4)
|
||||
err := proofServerClient.WaitReady(context.Background())
|
||||
require.NoError(t, err)
|
||||
t.Run("testGetProof", testGetProof)
|
||||
t.Run("testCancel", testCancel)
|
||||
}
|
||||
|
||||
func testAPIStatus(t *testing.T) {
|
||||
status, err := proofServerClient.apiStatus(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, status.Status.IsReady())
|
||||
}
|
||||
|
||||
func testCalculateProof(t *testing.T) {
|
||||
var zkInputs *common.ZKInputs
|
||||
zkInputs = common.NewZKInputs(100, 16, 512, 24, 32, big.NewInt(1))
|
||||
err := proofServerClient.CalculateProof(context.Background(), zkInputs)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func testGetProof(t *testing.T) {
|
||||
proof, err := proofServerClient.GetProof(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, proof)
|
||||
require.NotNil(t, proof.PiA)
|
||||
require.NotNil(t, proof.PiB)
|
||||
require.NotNil(t, proof.PiC)
|
||||
require.NotNil(t, proof.Protocol)
|
||||
}
|
||||
|
||||
func testCancel(t *testing.T) {
|
||||
var zkInputs *common.ZKInputs
|
||||
zkInputs = common.NewZKInputs(100, 16, 512, 24, 32, big.NewInt(1))
|
||||
err := proofServerClient.CalculateProof(context.Background(), zkInputs)
|
||||
require.NoError(t, err)
|
||||
// TODO: remove sleep when the server has been reviewed
|
||||
time.Sleep(time.Second / 4)
|
||||
err = proofServerClient.Cancel(context.Background())
|
||||
require.NoError(t, err)
|
||||
status, err := proofServerClient.apiStatus(context.Background())
|
||||
require.NoError(t, err)
|
||||
for status.Status == StatusCodeBusy {
|
||||
time.Sleep(proofServerClient.timeCons)
|
||||
status, err = proofServerClient.apiStatus(context.Background())
|
||||
require.NoError(t, err)
|
||||
}
|
||||
assert.Equal(t, StatusCodeAborted, status.Status)
|
||||
}
|
||||
Reference in New Issue
Block a user