Go Verifier API
Prerequisites to Run Verifier API
Each attestation type requires certain environment variables to be set. The following are common variables needed for all attestation types:
PORT=<port_number>
API_KEYS=<comma_separated_strings>
NOTE: The <port_number> value must be consistent with the PORT environment variable throughout the configuration.
TeeAvailabilityCheck Attestation Type
Environment variables:
VERIFIER_TYPE=TeeAvailabilityCheck
SOURCE_ID=TEE
RELAY_CONTRACT_ADDRESS=0x...
RPC_URL=https://<flare>
# Test/E2E-only flags (optional, default to false):
ALLOW_TEE_DEBUG=false
DISABLE_ATTESTATION_CHECK_E2E=false
ALLOW_PRIVATE_NETWORKS=false
NOTE: ALLOW_TEE_DEBUG, DISABLE_ATTESTATION_CHECK_E2E, and ALLOW_PRIVATE_NETWORKS are test/E2E-only flags. In production, you should leave them unset (they default to false). ALLOW_TEE_DEBUG=true additionally accepts debug-mode TEEs alongside production TEEs (every debug admission logs a WARN); debug TEEs have the debugger attached and secrets are extractable, so this must never be set on production deployments. ALLOW_PRIVATE_NETWORKS permits private/loopback IPs (e.g. Docker bridge 172.17.0.1) while still blocking dangerous IPs (link-local/metadata, multicast, Teredo, 6to4, IPv4-compatible IPv6) and preserving DNS pinning.
WARNING: MagicPass bypass — TEE nodes running in non-production mode (settings.Mode != 0) return "magic_pass" instead of a real attestation token. The verifier unconditionally accepts this token and skips ALL attestation validation (PKI, claims, CRL). This exists to support hackathon and development environments where real Google Confidential Space attestation is unavailable. Do NOT rely on this in production — any TEE returning this string will be trusted without verification.
The TeeAvailabilityCheck attestation type also uses Google Confidential Space Root Certificate, which is stored locally in the folder internal/config/assets. Read more about it here.
Environment variables:
VERIFIER_TYPE=PMWMultisigAccountConfigured
SOURCE_ID=testXRP
RPC_URL=https://<xrpl>
PMWPaymentStatus Attestation Type
You will need to run following indexers:
Environment variables:
VERIFIER_TYPE=PMWPaymentStatus
SOURCE_ID=testXRP
CCHAIN_DATABASE_URL=user:pass@tcp(host:port)/db?parseTime=true
SOURCE_DATABASE_URL=postgres://user:pass@host:port/db
FLARE_TEE_MANAGER_CONTRACT_ADDRESS=0x...
TEE_PAYMENTS_CONTRACT_ADDRESS=0x...
RPC_URL=https://<flare-c-chain>/ext/C/rpc
NOTE: FLARE_TEE_MANAGER_CONTRACT_ADDRESS is the on-chain contract that emits TeeInstructionsSent events. The verifier rejects indexed logs emitted by any other address.
NOTE: TEE_PAYMENTS_CONTRACT_ADDRESS is the source's TeePayments contract (deployed per source) — the verifier calls getInitialNonce on it for the deterministic paymentId→sequence binding. It is not the same as FLARE_TEE_MANAGER_CONTRACT_ADDRESS (the diamond that emits the events). RPC_URL is the Flare C-chain (EVM) RPC — same as TeeAvailabilityCheck — used for that call.
PMWFeeProof Attestation Type
Requires the same indexers as PMWPaymentStatus.
Environment variables:
VERIFIER_TYPE=PMWFeeProof
SOURCE_ID=testXRP
CCHAIN_DATABASE_URL=user:pass@tcp(host:port)/db?parseTime=true
SOURCE_DATABASE_URL=postgres://user:pass@host:port/db
FLARE_TEE_MANAGER_CONTRACT_ADDRESS=0x...
TEE_PAYMENTS_CONTRACT_ADDRESS=0x...
RPC_URL=https://<flare-c-chain>/ext/C/rpc
How to Set Up and Run Verifier
-
Fill in the .env file (for local development) or set environment variables directly (for production). To load the .env file at startup set LOAD_DOTENV=true in your shell before running the binary — .env loading is opt-in so production deployments are not sensitive to filesystem contents.
-
Install dependencies:
go mod tidy
-
Run the project:
go run ./cmd/main.go
For local development with a .env file, set LOAD_DOTENV=true so the binary loads it at startup:
LOAD_DOTENV=true go run ./cmd/main.go
In production, leave LOAD_DOTENV unset and inject environment variables via the container runtime.
-
Access Swagger UI:
http://localhost:<port_number>/api-doc
Replace <port_number> with the value set in your PORT environment variable.
API Reference
Base path for all verifier endpoints:
/verifier/<sourceName>/<attestationType>/
<sourceName> must be lowercase.
<attestationType> is the type of attestation (e.g., TeeAvailabilityCheck, PMWPaymentStatus, PMWMultisigAccountConfigured).
See API reference for endpoint definitions and examples.
Historical: TEE poller
An earlier version of TeeAvailabilityCheck ran a background poller that pinged active TEEs and maintained in-memory liveness samples. It was removed in favor of live-only verification. The last commit containing the full poller implementation is 70d8c33; check that commit out to inspect or restore the code.
Attestation Request Submission
The process of submitting an attestation requests is as follows:
Attestation requests are triggered via TEE smart contracts. The TEE relay client, which acts as a connector between contracts on Flare's C-chain and TEE clients, listens to TeeInstructionsSent events with an instructionId that correspond to an attestation request (FDC2_OP_TYPE ("F_FDC2") and PROVE ("PROVE")). Each attestation request is then placed into a queue and gradually promoted to the designated verifier server. It is advised that each TEE relay client runs its own verifier server.
Rate Limit
The blockchain itself limits how many attestation requests can be emitted per block, while the queue system enforces a controlled consumption rate for verifier servers. It is also expected that the person deploying the verifier server implements additional rate limiting at other levels.
For internal-only APIs, we use a minimal set of headers:
- FrameDeny – prevent clickjacking
- ContentTypeNosniff – prevent MIME sniffing
Other headers (CORS, SSL redirect, STS, cross-origin policies) are not needed because these services are only accessed internally by trusted services, not browsers or public clients.
Minimal headers keep internal communication safe without unnecessary overhead.
Running Tests
- Running all tests with coverage
sh gencover.sh
The script is located in gencover.sh.
- Docker services defined in internal/tests/docker/docker-compose.yaml will automatically start.
- All tests (unit + integration) will run.
- Docker services will automatically shut down after all tests complete.
This is the simplest way to run everything without worrying about Docker manually.
- Running specific tests manually
- The majority of tests are self-contained:
- A few tests (PMWPaymentStatus / PMWFeeProof) access the indexer databases and are Docker-dependent. They are gated behind the
integration build tag, so a bare go test ./... skips them and stays green without Docker.
- Start Docker manually:
docker compose -f internal/tests/docker/docker-compose.yaml up -d
- Run the integration tests (note
-tags integration):
go test -tags integration -v <path_to_test>
- Stop Docker after finishing:
docker compose -f internal/tests/docker/docker-compose.yaml down
-
Running fuzz tests
Fuzz tests run their seed corpus as regular tests during go test and gencover.sh. To run actual fuzzing with random inputs:
go test ./internal/attestation/teeavailabilitycheck/verifier/ -fuzz FuzzResolveExternalURL -fuzztime 60s
Available fuzz targets: FuzzResolveExternalURL, FuzzGetOrFetchCRL, FuzzFetchCRLsForToken, FuzzFetchTEEChallengeResult.
-
Running benchmarks
Benchmark tests measure PMWFeeProof performance scaling with real Postgres + MySQL. They require Docker and are gated behind the docker_bench build tag:
docker compose -f internal/tests/docker/docker-compose.yaml up -d
# Sequential benchmark (single client, varying batch ranges):
go test -tags docker_bench -run TestBenchmarkFeeProofPostgres -v ./internal/attestation/pmwfeeproof/xrp/
# Concurrent benchmark (multiple clients, varying batch ranges):
go test -tags docker_bench -run TestBenchmarkFeeProofConcurrent -v ./internal/attestation/pmwfeeproof/xrp/
docker compose -f internal/tests/docker/docker-compose.yaml down
-
Running load tests
Load tests are gated behind the load build tag and don't run during normal go test or gencover.sh:
go test -tags load -run TestLoad -v ./internal/attestation/teeavailabilitycheck/verifier/ ./internal/attestation/pmwmultisigconfigured/xrp/ ./internal/attestation/pmwpaymentstatus/db/ ./internal/attestation/pmwpaymentstatus/xrp/ ./internal/attestation/pmwfeeproof/db/ ./internal/attestation/pmwfeeproof/xrp/
-
Running stress tests
Stress tests are gated behind the stress build tag. They take longer (~70s) and push beyond normal load:
go test -tags stress -run TestStress -v ./internal/attestation/teeavailabilitycheck/verifier/
For detailed results, findings, and test parameters, see docs/load-and-stress-tests.md.
TODO (to-think-about) list
- Other
TODOs inside the code and README.
- TEEAvailabilityCheck currently supports only "google". When support for other platforms is added, TeeInfo.Platform needs to be added in order to know, how to decode the data.
- PMWFeeProof: Confirm with FAsset team that the
estimatedFee formula (pay_maxFee + sum(max(0, reissue_maxFee - pay_maxFee))) is suitable for their fee reconciliation use case.
go.mod pins github.com/jackc/pgx/v5 v5.9.1 as an explicit indirect override because gorm.io/driver/postgres v1.6.0 pulls the unpatched v5.6.0 (CVE-2026-33815, CVE-2026-33816). Drop the explicit pgx require once a newer gorm.io/driver/postgres ships that pulls pgx >= v5.9.0.
Technical Specification
See docs/SPEC.md for the full technical specification covering architecture, verification flows, error model, and configuration.