Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add publicStatesInfo into circuit inputs response #86

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
6 changes: 3 additions & 3 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ on:

jobs:
lint:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 1.22.5
go-version: 1.23.4
- uses: golangci/golangci-lint-action@v6
with:
version: v1.59.1
version: v1.63.4
2 changes: 1 addition & 1 deletion .github/workflows/tests-c.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
matrix:
containers:
- 1.22.5-bookworm
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
container: golang:${{matrix.containers}}
steps:
- uses: actions/checkout@v4
Expand Down
21 changes: 8 additions & 13 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,18 @@ jobs:
test:
strategy:
matrix:
containers:
- 1.22.5-bookworm
runs-on: ubuntu-20.04
container: golang:${{ matrix.containers }}
go_version:
- "1.22.10"
- "1.23.4"
runs-on: ubuntu-24.04
env:
IPFS_URL: http://ipfs:5001
IPFS_URL: http://localhost:5001
steps:
- uses: actions/checkout@v4
- uses: actions/cache@v4
- uses: actions/setup-go@v5
with:
path: |
~/.cache/go-build
/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- run: go test -race -timeout=60s -find-unused-httpresp ./...
go-version: ${{ matrix.go_version }}
- run: go test -v -race -timeout=60s ./... -find-unused-httpresp
services:
ipfs:
image: ipfs/kubo:v0.26.0
Expand Down
61 changes: 46 additions & 15 deletions cmd/polygonid/polygonid.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,11 @@ func maybeCreateStatus(status **C.PLGNStatus, code C.PLGNStatusCode,
*status = s
}

// Deprecated: Use PLGNAGenerateInputs with additional
// `"request": {"circuitId": "authV2"}` in the request json. This function
// does not support `statsInfo` in response and returns inputs
// on top level of response object.
//
//export PLGNAuthV2InputsMarshal
func PLGNAuthV2InputsMarshal(jsonResponse **C.char, in *C.char,
status **C.PLGNStatus) bool {
Expand Down Expand Up @@ -610,6 +615,7 @@ func marshalInputsResponse(
var resp struct {
Inputs json.RawMessage `json:"inputs"`
VerifiablePresentation any `json:"verifiablePresentation,omitempty"`
PublicStatesInfo json.RawMessage `json:"publicStatesInfo,omitempty"`
}
if inputsResponse.VerifiablePresentation != nil {
resp.VerifiablePresentation = inputsResponse.VerifiablePresentation
Expand All @@ -620,6 +626,18 @@ func marshalInputsResponse(
return "", err
}

i, ok := inputsResponse.Inputs.(circuits.PublicStatesInfoProvider)
if ok {
publicStatesInfo, err := i.GetPublicStatesInfo()
if err != nil {
return "", err
}
resp.PublicStatesInfo, err = json.Marshal(publicStatesInfo)
if err != nil {
return "", err
}
}

respBytes, err := json.Marshal(resp)
if err != nil {
return "", err
Expand Down Expand Up @@ -751,6 +769,20 @@ func PLGNALinkedMultiQueryInputs(jsonResponse **C.char, in *C.char,
jsonResponse, in, cfg, status)
}

// PLGNAGenerateInputs returns the inputs for the circuit based on the
// request.circuitId field.
//
//export PLGNAGenerateInputs
func PLGNAGenerateInputs(jsonResponse **C.char, in *C.char,
cfg *C.char, status **C.PLGNStatus) bool {

ctx, cancel := logAPITime()
defer cancel()

return prepareInputs(ctx, c_polygonid.GenericInputsFromJson,
jsonResponse, in, cfg, status)
}

//export PLGNFreeStatus
func PLGNFreeStatus(status *C.PLGNStatus) {
_, cancel := logAPITime()
Expand Down Expand Up @@ -790,7 +822,7 @@ func PLGNCleanCache2(cfg *C.char, status **C.PLGNStatus) bool {
_, cancel := logAPITime()
defer cancel()

envCfg, err := createEnvConfig(cfg)
envCfg, err := c_polygonid.NewEnvConfigFromJSON(cStrToGoSlice(cfg))
if err != nil {
maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error())
return false
Expand All @@ -815,7 +847,7 @@ func PLGNCacheCredentials(in *C.char, cfg *C.char, status **C.PLGNStatus) bool {

inData := C.GoBytes(unsafe.Pointer(in), C.int(C.strlen(in)))

envCfg, err := createEnvConfig(cfg)
envCfg, err := c_polygonid.NewEnvConfigFromJSON(cStrToGoSlice(cfg))
if err != nil {
maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error())
return false
Expand Down Expand Up @@ -868,7 +900,7 @@ func PLGNW3CCredentialFromOnchainHex(jsonResponse **C.char, in *C.char,

inData := C.GoBytes(unsafe.Pointer(in), C.int(C.strlen(in)))

envCfg, err := createEnvConfig(cfg)
envCfg, err := c_polygonid.NewEnvConfigFromJSON(cStrToGoSlice(cfg))
if err != nil {
maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error())
return false
Expand Down Expand Up @@ -925,7 +957,7 @@ func PLGNDescribeID(jsonResponse **C.char, in *C.char, cfg *C.char,
return false
}

envCfg, err := createEnvConfig(cfg)
envCfg, err := c_polygonid.NewEnvConfigFromJSON(cStrToGoSlice(cfg))
if err != nil {
maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error())
return false
Expand Down Expand Up @@ -988,15 +1020,6 @@ func PLGNBabyJubJubPublicCompress(jsonResponse **C.char, in *C.char,
in, cfg, status)
}

// createEnvConfig returns empty config if input json is nil.
func createEnvConfig(cfgJson *C.char) (c_polygonid.EnvConfig, error) {
var cfgData []byte
if cfgJson != nil {
cfgData = C.GoBytes(unsafe.Pointer(cfgJson), C.int(C.strlen(cfgJson)))
}
return c_polygonid.NewEnvConfigFromJSON(cfgData)
}

type atomicQueryInputsFn func(ctx context.Context, cfg c_polygonid.EnvConfig,
in []byte) (c_polygonid.AtomicQueryInputsResponse, error)

Expand All @@ -1015,7 +1038,7 @@ func prepareInputs(ctx context.Context, fn atomicQueryInputsFn,

inData := C.GoBytes(unsafe.Pointer(in), C.int(C.strlen(in)))

envCfg, err := createEnvConfig(cfg)
envCfg, err := c_polygonid.NewEnvConfigFromJSON(cStrToGoSlice(cfg))
if err != nil {
maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error())
return false
Expand Down Expand Up @@ -1094,6 +1117,14 @@ func statusFromError(err error) (C.PLGNStatusCode, string) {
return C.PLGNSTATUSCODE_ERROR, err.Error()
}

func cStrToGoSlice(in *C.char) []byte {
var out []byte
if in != nil {
out = C.GoBytes(unsafe.Pointer(in), C.int(C.strlen(in)))
}
return out
}

func callGenericFn[R any](
fn func(context.Context, c_polygonid.EnvConfig, []byte) (R, error),
jsonResponse **C.char, in *C.char, cfg *C.char,
Expand All @@ -1108,7 +1139,7 @@ func callGenericFn[R any](
return false
}

envCfg, err := createEnvConfig(cfg)
envCfg, err := c_polygonid.NewEnvConfigFromJSON(cStrToGoSlice(cfg))
if err != nil {
maybeCreateStatus(status, C.PLGNSTATUSCODE_ERROR, "%v", err.Error())
return false
Expand Down
111 changes: 111 additions & 0 deletions cmd/polygonid/polygonid_test.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,47 @@
package main

import (
"context"
"encoding/hex"
"encoding/json"
"flag"
"log/slog"
"math/big"
"math/rand"
"os"
"strings"
"testing"
"time"

c_polygonid "github.com/0xPolygonID/c-polygonid"
httpmock "github.com/0xPolygonID/c-polygonid/testing"
core "github.com/iden3/go-iden3-core/v2"
"github.com/iden3/go-iden3-crypto/poseidon"
"github.com/stretchr/testify/require"
)

var catchUnusedHttpresp = flag.Bool("find-unused-httpresp", false,
"fail if there are unused httpresp_* files")

func TestMain(m *testing.M) {
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
AddSource: true,
Level: slog.LevelInfo,
ReplaceAttr: nil,
})))

retCode := m.Run()
flag.Parse()

if *catchUnusedHttpresp {
if !httpmock.CheckForRedundantHttpresps("testdata", "httpresp_") {
os.Exit(1)
}
}

os.Exit(retCode)
}

func TestGenerateAuthClaimData(t *testing.T) {
t.Skip("generate auth claim data")
var schema core.SchemaHash
Expand Down Expand Up @@ -127,3 +155,86 @@ func TestCreateClaimAllFields2(t *testing.T) {

t.Log(string(cBytes))
}

func readFixtureFile(name string) []byte {
fileBytes, err := os.ReadFile("testdata/" + name)
if err != nil {
panic(err)
}
return fileBytes
}

func TestGenrateInputs(t *testing.T) {
type PrepareInputsFn func(
ctx context.Context, cfg c_polygonid.EnvConfig, in []byte) (
c_polygonid.AtomicQueryInputsResponse, error)

cacheDir, err := os.MkdirTemp("", "")
require.NoError(t, err)
t.Cleanup(func() {
err := os.RemoveAll(cacheDir)
require.NoError(t, err)
})

doTest := func(t testing.TB, inFile, wantOutFile string,
fn PrepareInputsFn, wantVR map[string]any, cfg c_polygonid.EnvConfig,
wantErr string) {

err := c_polygonid.CleanCache(cacheDir)
require.NoError(t, err)

ctx := context.Background()
out, err := fn(ctx, cfg, readFixtureFile(inFile))
if wantErr != "" {
require.EqualError(t, err, wantErr)
return
}
require.NoError(t, err)

resp, err := marshalInputsResponse(out)
require.NoError(t, err)

assertEqualWithoutTimestamp(t, wantOutFile, resp)
}

env := c_polygonid.EnvConfig{CacheDir: cacheDir}
t.Run("atomic_query_v3_on_chain_mtp_inputs", func(t *testing.T) {
defer httpmock.MockHTTPClient(t, map[string]string{
"http://localhost:8001/api/v1/identities/did%3Apolygonid%3Apolygon%3Amumbai%3A2qDnyCaxj4zdYmj6LbegYMjWSnkbKAyqtq31YeuyZV/claims/revocation/status/3972757": "../../testdata/httpresp_rev_status_3972757.json",
"https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v3.json-ld": "../../testdata/httpresp_kyc-v3.json-ld",
"https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/iden3credential-v2.json-ld": "../../testdata/httpresp_iden3credential_v2.json",
})()

doTest(t, "atomic_query_v3_on_chain_mtp_inputs.json",
"atomic_query_v3_on_chain_mtp_output.json",
c_polygonid.AtomicQueryV3OnChainInputsFromJson, nil, env, "")
})
t.Run("auth_v2_inputs", func(t *testing.T) {
doTest(t, "auth_v2_inputs_in.json", "auth_v2_inputs_out.json",
c_polygonid.AuthV2InputsFromJson, nil, env, "")
})

}

func assertEqualWithoutTimestamp(t testing.TB, wantFName string,
actual string) {

jsonWant := readFixtureFile(wantFName)
var wantObj map[string]any
err := json.Unmarshal(jsonWant, &wantObj)
require.NoError(t, err)

var actualObj map[string]any
err = json.Unmarshal([]byte(actual), &actualObj)
require.NoError(t, err)

actualInputsObj, ok := actualObj["inputs"].(map[string]any)
require.True(t, ok)

if ts, ok := actualInputsObj["timestamp"]; ok {
wantObj["inputs"].(map[string]any)["timestamp"] = ts
}

require.Equal(t, wantObj, actualObj, "file name: %s\nwant: %s\ngot: %s",
wantFName, jsonWant, actual)
}
Loading