Conversation
|
| identifier: "https://issuer.sunet.se" | ||
| wallet_url: "" | ||
| issuer_url: "http://apigw.vc.docker:8080" | ||
| signing_key_path: "/pki/signing_ec_private.pem" |
There was a problem hiding this comment.
use key_config, it has capability to use pkcs11 as well as crypto material on disk.
|
|
||
| issuer: | ||
| issuer_url: "http://apigw.vc.docker:8080" | ||
| identifier: "https://issuer.sunet.se" |
There was a problem hiding this comment.
identifier is not used anymore.
| # This must match the DocType in your curl | ||
| doc_type: "org.iso.18013.5.1.mDL" | ||
| certificate_chain_path: "/pki/signing_ec_chain.pem" | ||
| # This is the namespace your Rust code expects |
| static_host: "http://vc_dev_portal:8080/statics" | ||
| mdoc: | ||
| valid_duration: 3600 | ||
| signing_key_path: "/pki/signing_ec_private.pem" |
| - "eduid" | ||
| zk: | ||
| ca_certs_path: "/app/vc/internal/verifier/zk/certs.pem" | ||
| circuits_path: "/app/vc/internal/verifier/zk/circuits/" |
There was a problem hiding this comment.
is circuits_path the same as a path to a lib?
| reply := &VerifyZKPResponse{ | ||
| Status: ok, | ||
| Claims: map[string][]ClaimElement{ | ||
| "org.iso.18013.5.1": apiClaims, |
There was a problem hiding this comment.
in configuration, the key for "org.iso.18013.5.1" is named namespace, but here it's a vc type. What is it?
I notice that the mDL manual refers to org.iso.18013.5.1 as a namespace, but this application must deal with many different kinds of credentials.
There was a problem hiding this comment.
is zkp a thing for other credential types other then mDoc?
| notify: notify, | ||
| tracer: tracer, | ||
| server: &http.Server{}, // Timeouts and other defaults are set by httphelpers.Server.Default | ||
| server: &http.Server{ |
There was a problem hiding this comment.
have you tested with the default and found it won't worked?
| s.httpHelpers.Server.RegEndpoint(ctx, rgOIDCVerification, http.MethodPost, "confirm/:session_id", http.StatusOK, s.endpointConfirmCredentialDisplay) | ||
|
|
||
| // Longfellow-zk verifier | ||
| s.httpHelpers.Server.RegEndpoint(ctx, rgOIDCVerification, http.MethodPost, "verifyzkp", http.StatusOK, s.endpointVerifyZKP) |
There was a problem hiding this comment.
should this endpoint be in oidc space?
|
|
||
| type ZKConfig struct { | ||
| // Note the envconfig tags - this is how the loader finds them! | ||
| CACertsPath string `yaml:"ca_certs_path" envconfig:"VERIFIER_ZK_CA_CERTS" validate:"required"` |
There was a problem hiding this comment.
No envconfig please, stick with configuration file.
|
|
||
| func (s *Service) endpointVerifyZKP(ctx context.Context, c *gin.Context) (any, error) { | ||
| s.log.Debug("endpointVerificationDirectPost called") | ||
| c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 2*1024*1024) |
There was a problem hiding this comment.
maybe this project should have a middleware default to prevent too big body?
There was a problem hiding this comment.
Pull request overview
This PR adds Longfellow ZK proof verification support to the verifier service (behind a zk build tag) and introduces an HTTP endpoint in the issuer service to issue ISO 18013-5 mdoc credentials.
Changes:
- Add a
POST /verification/verifyzkpverifier endpoint and ZK proof handling (CBOR parsing + CGO bridge to Longfellow verifier). - Add a
POST /mdocissuer endpoint to issue mdoc credentials. - Add build/packaging plumbing for ZK (Dockerfile, Makefile tags, CI steps, config fields).
Reviewed changes
Copilot reviewed 23 out of 29 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
| vendor/proofs/server/v2/zk/vical.go | Fetch and load VICAL issuer roots into a cert pool. |
| vendor/proofs/server/v2/zk/roots.go | Global issuer root cert pool for ZK verification. |
| vendor/proofs/server/v2/zk/proofs.go | CGO bridge to Longfellow ZK verifier library and proof verification entrypoint. |
| vendor/proofs/server/v2/zk/circuits.go | Load circuits from disk and validate via circuit-id. |
| vendor/proofs/server/v2/zk/cbor.go | Parse ZKDeviceResponse CBOR formats and validate issuer cert chain. |
| vendor/modules.txt | Vendor metadata for the added proofs/server/v2 module. |
| sonar-project.properties | Adjust Sonar exclusions/ignore criteria (Dockerfiles). |
| pkg/model/config.go | Add verifier zk config block (paths for CA/circuits/libs). |
| internal/verifier/httpserver/service.go | Register ZK verification endpoint and adjust server timeouts. |
| internal/verifier/httpserver/endpoint_verification.go | Implement HTTP handler for verifyzkp. |
| internal/verifier/httpserver/api.go | Extend verifier API interface with VerifyZKP. |
| internal/verifier/apiv1/handlers_verification_zk_enabled.go | Implement ZK verification handler (enabled build). |
| internal/verifier/apiv1/handlers_verification_zk_disabled.go | Implement ZK verification handler (disabled build). |
| internal/verifier/apiv1/handlers_verification.go | Add request/response types for ZK verification. |
| internal/verifier/apiv1/handler_verification_zk_enabled_test.go | Add zk-tagged unit test for VerifyZKP (enabled). |
| internal/verifier/apiv1/handler_verification_zk_disabled_test.go | Add non-zk unit test for VerifyZKP (disabled). |
| internal/issuer/httpserver/service.go | Register POST /mdoc endpoint; switch apiv1 field to concrete client. |
| internal/issuer/httpserver/endpoints.go | Implement HTTP handler for mdoc issuance. |
| internal/issuer/apiv1/handlers_test.go | Add a basic mdoc issuance test. |
| go.mod | Add proofs/server/v2 requirement and local filesystem replace. |
| dockerfiles/worker | Switch builds to -mod=vendor and change dependency step. |
| dockerfiles/verifier.Dockerfile | Add a dedicated verifier image build that compiles Longfellow ZK libs + Go binary. |
| docker-compose.yaml | Adjust verifier image name for compose. |
| config.yaml | Add example issuer mdoc + verifier zk config; modify issuer settings. |
| cmd/verifier/zk_enabled_setup.go | Add verifier startup initialization for circuits + CA roots (zk build). |
| cmd/verifier/zk_disabled_setup.go | No-op ZK setup when zk build tag is off. |
| cmd/verifier/main.go | Call setupZK during verifier startup. |
| Makefile | Add ZK build tag plumbing, docker build target, and test target. |
| .github/workflows/test.yaml | Clone longfellow-zk into /tmp and run go mod tidy/vendor in CI. |
Comments suppressed due to low confidence (1)
go.mod:219
replace proofs/server/v2 => /tmp/...hard-codes a local filesystem path, making builds non-reproducible and breaking for anyone (and any CI runner) without that exact directory layout. This should be replaced with a repository-relative path committed to this repo (e.g., athird_party/checkout) or an actual VCS module path + version; avoid/tmpin go.mod.
proofs/server/v2 v2.0.0
)
require (
dario.cat/mergo v1.0.2 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/PaesslerAG/gval v1.2.4 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bytedance/gopkg v0.1.4 // indirect
github.com/bytedance/sonic v1.15.0 // indirect
github.com/bytedance/sonic/loader v0.5.0 // indirect
github.com/cayleygraph/quad v1.3.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudwego/base64x v0.1.6 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/docker v28.5.1+incompatible // indirect
github.com/docker/go-connections v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/eapache/go-resiliency v1.7.0 // indirect
github.com/eapache/queue v1.1.0 // indirect
github.com/ebitengine/purego v0.8.4 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/gabriel-vasile/mimetype v1.4.13 // indirect
github.com/gin-contrib/sse v1.1.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-openapi/jsonpointer v0.22.5 // indirect
github.com/go-openapi/jsonreference v0.21.5 // indirect
github.com/go-openapi/spec v0.22.4 // indirect
github.com/go-openapi/swag/conv v0.25.5 // indirect
github.com/go-openapi/swag/jsonname v0.25.5 // indirect
github.com/go-openapi/swag/jsonutils v0.25.5 // indirect
github.com/go-openapi/swag/loading v0.25.5 // indirect
github.com/go-openapi/swag/stringutils v0.25.5 // indirect
github.com/go-openapi/swag/typeutils v0.25.5 // indirect
github.com/go-openapi/swag/yamlutils v0.25.5 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/goccy/go-json v0.10.6 // indirect
github.com/goccy/go-yaml v1.19.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/gorilla/context v1.1.2 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
github.com/jcmturner/gofork v1.7.6 // indirect
github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/jonboulle/clockwork v0.5.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kaptinlin/go-i18n v0.2.12 // indirect
github.com/kaptinlin/jsonpointer v0.4.17 // indirect
github.com/kaptinlin/messageformat-go v0.4.18 // indirect
github.com/klauspost/compress v1.18.4 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lestrrat-go/blackmagic v1.0.4 // indirect
github.com/lestrrat-go/dsig v1.0.0 // indirect
github.com/lestrrat-go/dsig-secp256k1 v1.0.0 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/httprc/v3 v3.0.4 // indirect
github.com/lestrrat-go/option/v2 v2.0.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.10 // indirect
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/go-archive v0.1.0 // indirect
github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect
github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pierrec/lz4/v4 v4.1.26 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/pquerna/cachecontrol v0.2.0 // indirect
github.com/prometheus/client_golang v1.23.2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.66.1 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/quic-go/quic-go v0.59.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect
github.com/richardlehane/mscfb v1.0.6 // indirect
github.com/richardlehane/msoleps v1.0.6 // indirect
github.com/segmentio/asm v1.2.1 // indirect
github.com/shirou/gopsutil/v4 v4.25.6 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sirosfoundation/g119612 v0.0.0-20260108094825-5b3123230280 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/tiendc/go-deepcopy v1.7.2 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.3.1 // indirect
github.com/valyala/fastjson v1.6.10 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.2.0 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/xuri/efp v0.0.1 // indirect
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 // indirect
go.opentelemetry.io/otel/metric v1.42.0 // indirect
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/arch v0.25.0 // indirect
golang.org/x/mod v0.34.0 // indirect
golang.org/x/net v0.52.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect
golang.org/x/tools v0.43.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260316180232-0b37fe3546d5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260316180232-0b37fe3546d5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
replace proofs/server/v2 => /tmp/longfellow-zk/reference/verifier-service/server
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| { | ||
| name: "process valid base64 payload", | ||
| req: &VerifyZKPRequest{ | ||
| Transcript: transcript, | ||
| ZKDeviceResponseCBOR: deviceCBOR, | ||
| }, | ||
| expectError: false, | ||
| }, |
There was a problem hiding this comment.
This test expects the "valid base64 payload" case to succeed, but VerifyZKP depends on runtime state that isn't initialized in the test (trusted issuer roots loaded into IssuerRoots, circuits loaded into the circuit map, and the CGO verifier library available at link/runtime). As written, this will be flaky or fail whenever the zk tag is enabled. Consider mocking zk.VerifyProofRequest/issuer validation, or make the test assert only the decoding/validation behavior and skip proof verification unless an explicit integration-test flag/env is set.
|
|
||
| test-all-tags: ## Test with all build tags | ||
| $(info Testing with all build tags) | ||
| go test -tags "$(SAML_TAG),$(OIDCRP_TAG),$(VC20_TAG),$(PKCS11_TAG), $(ZK_TAG)" -v ./... |
There was a problem hiding this comment.
There is an extra space before $(ZK_TAG) in the -tags list. Go's -tags flag expects a clean comma-separated list; the space can lead to an invalid/ignored tag depending on parsing. Remove the space to ensure zk is actually enabled when running this target.
| go test -tags "$(SAML_TAG),$(OIDCRP_TAG),$(VC20_TAG),$(PKCS11_TAG), $(ZK_TAG)" -v ./... | |
| go test -tags "$(SAML_TAG),$(OIDCRP_TAG),$(VC20_TAG),$(PKCS11_TAG),$(ZK_TAG)" -v ./... |
| - name: Sync dependencies | ||
| run: | | ||
| go mod tidy | ||
| go mod vendor |
There was a problem hiding this comment.
Running go mod tidy + go mod vendor inside CI mutates go.mod/go.sum/vendor during the workflow, which makes the build non-deterministic and can mask the fact that the repo isn't kept tidy/vendor'd in git. It also works around the /tmp-based replace rather than fixing it. Prefer committing the correct module dependency (or removing the local replace) and have CI verify go mod tidy/go mod vendor are already clean (or run tests with -mod=vendor without rewriting files).
| - name: Sync dependencies | |
| run: | | |
| go mod tidy | |
| go mod vendor | |
| - name: Verify dependencies are tidy and vendored | |
| run: | | |
| go mod tidy | |
| go mod vendor | |
| git diff --exit-code -- go.mod go.sum vendor/ |
| // Longfellow-zk verifier | ||
| s.httpHelpers.Server.RegEndpoint(ctx, rgOIDCVerification, http.MethodPost, "verifyzkp", http.StatusOK, s.endpointVerifyZKP) | ||
|
|
There was a problem hiding this comment.
PR description says the verifier endpoint is Verifier_URL/verification/verify, but the route registered here is POST /verification/verifyzkp. Either update the route to match the documented path or update the PR description/docs so operators know the correct endpoint.
| func TestMakeMDoc_Only(t *testing.T) { | ||
| ctx := context.Background() | ||
| log := logger.NewSimple("test") | ||
| client := mockNewClient(ctx, t, "ecdsa", log) | ||
|
|
||
| realIssuer := &mdoc.Issuer{} | ||
|
|
||
| client.mdocIssuer = realIssuer | ||
|
|
||
| deviceKeyHex := "a501020326200121582065eda5bd2d497ef0d35502f5846014e4a66a17ef65476a029587428f6426466322582042f4c664323c932a393086603a1f81d894e77227ed9097e38317769539257609" | ||
| deviceKeyBytes, _ := hex.DecodeString(deviceKeyHex) | ||
|
|
||
| req := &CreateMDocRequest{ | ||
| Scope: "mdl", | ||
| DocType: "org.iso.18013.5.1.mDL", | ||
| DocumentData: []byte(`{"given_name": "John"}`), | ||
| DevicePublicKey: deviceKeyBytes, | ||
| DeviceKeyFormat: "cose", | ||
| } | ||
|
|
||
| got, err := client.MakeMDoc(ctx, req) | ||
| if err != nil { | ||
| t.Logf("Note: Real issuer failed (likely missing keys): %v", err) | ||
| } else { | ||
| require.NoError(t, err) | ||
| assert.NotNil(t, got) | ||
| } |
There was a problem hiding this comment.
This test logs and continues on error, so it can pass even if MakeMDoc is broken (and it likely will fail in many environments if signing keys/config aren't present). To make it meaningful, either fully mock mdoc.Issuer and assert deterministic behavior, or turn this into an explicit integration test that is skipped unless required test fixtures/env are present.
| if cfg.Verifier == nil || cfg.Verifier.ZK.CircuitsPath == "" || cfg.Verifier.ZK.CACertsPath == "" { | ||
| return fmt.Errorf("ZK build requires circuits_path and cacerts_path in config") | ||
| } | ||
| zk.LoadCircuits(cfg.Verifier.ZK.CircuitsPath) |
There was a problem hiding this comment.
setupZK ignores the error return from zk.LoadCircuits(...), so verifier startup will succeed even if circuits fail to load (and later verification requests will fail unexpectedly). Also cfg.Verifier.ZK.LibPath is required in config but never used here. Please handle/return the LoadCircuits error and either remove LibPath from config or use it (e.g., to configure library search path) so the config contract matches behavior.
| if cfg.Verifier == nil || cfg.Verifier.ZK.CircuitsPath == "" || cfg.Verifier.ZK.CACertsPath == "" { | |
| return fmt.Errorf("ZK build requires circuits_path and cacerts_path in config") | |
| } | |
| zk.LoadCircuits(cfg.Verifier.ZK.CircuitsPath) | |
| if cfg.Verifier == nil || cfg.Verifier.ZK.CircuitsPath == "" || cfg.Verifier.ZK.CACertsPath == "" || cfg.Verifier.ZK.LibPath == "" { | |
| return fmt.Errorf("ZK build requires circuits_path, cacerts_path, and lib_path in config") | |
| } | |
| if err := os.Setenv("LD_LIBRARY_PATH", cfg.Verifier.ZK.LibPath); err != nil { | |
| return fmt.Errorf("could not set ZK library path: %w", err) | |
| } | |
| if err := zk.LoadCircuits(cfg.Verifier.ZK.CircuitsPath); err != nil { | |
| return fmt.Errorf("could not load ZK circuits: %w", err) | |
| } |
| server: &http.Server{ | ||
| ReadHeaderTimeout: 5 * time.Second, | ||
| ReadTimeout: 30 * time.Second, | ||
| WriteTimeout: 60 * time.Second, | ||
| IdleTimeout: 120 * time.Second, | ||
| }, |
There was a problem hiding this comment.
The timeouts set on http.Server here will be overwritten by httphelpers.Server.Default(...) (which unconditionally sets Read/Write/Idle/ReadHeader timeouts). As-is, this block is misleading and effectively dead code; either rely on Default (and remove this) or change Default/the call site so the intended verifier-specific timeouts actually take effect.
| cfg *model.Cfg | ||
| log *logger.Log | ||
| server *http.Server | ||
| apiv1 Apiv1 | ||
| apiv1 *apiv1.Client | ||
| gin *gin.Engine | ||
| tracer *trace.Tracer | ||
| httpHelpers *httphelpers.Client |
There was a problem hiding this comment.
Switching Service.apiv1 from an interface to a concrete *apiv1.Client reduces testability and bypasses the existing internal/issuer/httpserver/api.go abstraction. Instead, extend the Apiv1 interface to include MakeMDoc and keep Service.apiv1 typed as that interface so handlers can be unit-tested with mocks.
| Transcript string `json:"Transcript"` | ||
| ZKDeviceResponseCBOR string `json:"ZKDeviceResponseCBOR"` | ||
| } | ||
|
|
||
| type ClaimElement struct { | ||
| ElementIdentifier string `json:"ElementIdentifier"` | ||
| ElementValue string `json:"ElementValue"` | ||
| } | ||
|
|
||
| type VerifyZKPResponse struct { | ||
| Status bool `json:"Status"` | ||
| Claims map[string][]ClaimElement `json:"Claims"` |
There was a problem hiding this comment.
These JSON tags are capitalized (e.g., "Transcript") and the request has no validation tags. This is inconsistent with the rest of the API (which uses lowercase/snake_case tags + validate:"required") and will surprise clients/binders. Suggest switching to consistent lowercase JSON field names and adding validation tags (and/or helpers.Check) to ensure required fields are present.
| Transcript string `json:"Transcript"` | |
| ZKDeviceResponseCBOR string `json:"ZKDeviceResponseCBOR"` | |
| } | |
| type ClaimElement struct { | |
| ElementIdentifier string `json:"ElementIdentifier"` | |
| ElementValue string `json:"ElementValue"` | |
| } | |
| type VerifyZKPResponse struct { | |
| Status bool `json:"Status"` | |
| Claims map[string][]ClaimElement `json:"Claims"` | |
| Transcript string `json:"transcript" validate:"required"` | |
| ZKDeviceResponseCBOR string `json:"zk_device_response_cbor" validate:"required"` | |
| } | |
| type ClaimElement struct { | |
| ElementIdentifier string `json:"element_identifier"` | |
| ElementValue string `json:"element_value"` | |
| } | |
| type VerifyZKPResponse struct { | |
| Status bool `json:"status"` | |
| Claims map[string][]ClaimElement `json:"claims"` |
| } | ||
|
|
||
| func (s *Service) endpointVerifyZKP(ctx context.Context, c *gin.Context) (any, error) { | ||
| s.log.Debug("endpointVerificationDirectPost called") |
There was a problem hiding this comment.
The debug log message in this endpoint says endpointVerificationDirectPost called, which looks like a copy/paste and makes logs confusing when debugging ZK requests. Update it to the correct endpoint name (e.g., endpointVerifyZKP called).
| s.log.Debug("endpointVerificationDirectPost called") | |
| s.log.Debug("endpointVerifyZKP called") |


Summary
This PR integrates longfellow-zk into the verifier, following the reference implementation. It also enables the issuer service to issue mdoc verifiable credentials (VCs).
Type of change
Related issues / tickets
Changes
The issuer service accepts mdoc VC requests via the mdoc endpoint
The issuer issues mdoc VCs
The verifier service loads the ZK circuits during initialization.
It accepts the proof as a JSON file from the holder.
It verifies the proof and returns the result.
Architecture decisions
Screenshots / recordings (if UI changes)
How to test
Issuer :
1, Deploy the issuer service.
2, Send a request to Issuer_URL/mdoc including the scope, document data, and other parameters in the payload.
Verifier:
1, Deploy the verifier service.
2, Get an example proof from https://github.com/google/longfellow-zk/tree/main/reference/verifier-service/server/examples
3, Make a call to Verifier_URL/verification/verify.
Checklist
Notes for reviewers