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 thePORTenvironment variable throughout the configuration.
Environment variables:
VERIFIER_TYPE=TeeAvailabilityCheck
SOURCE_ID=TEE
RELAY_CONTRACT_ADDRESS=0x...
TEE_MACHINE_REGISTRY_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=falseNOTE:
ALLOW_TEE_DEBUG,DISABLE_ATTESTATION_CHECK_E2E, andALLOW_PRIVATE_NETWORKSare test/E2E-only flags. In production, you should leave them unset (they default to false).ALLOW_PRIVATE_NETWORKSpermits private/loopback IPs (e.g. Docker bridge172.17.0.1) while still blocking dangerous IPs (link-local/metadata, multicast, Teredo, 6to4) 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>
You will need to run following indexers:
- xrp-indexer (not yet publicly available)
- c-chain indexer
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/dbRequires 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-
Fill in the
.envfile or set environment variables according to the attestation type. -
Install dependencies:
go mod tidy
To update
go-flare-commonto the latest commit onteebranch, rungo get github.com/flare-foundation/go-flare-common@<commitHash> -
Run the project:
go run ./cmd/main.go
-
Access Swagger UI:
http://localhost:<port_number>/api-docReplace
<port_number>with the value set in yourPORTenvironment variable.
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.
The TeeAvailabilityCheck attestation type initiates a process called tee_poller. The purpose of the tee_poller is to continuously ping all available TEEs (retrieved from the TeeMachineRegistry smart contract), verify the freshness of the challenge and the correctness of the attestation, and detect whether any TEEs are no longer available, which enables the system to provide a proof that a TEE machine is DOWN.
Samples retrieved by the poller can be VALID, INVALID or INDETERMINATE (the latter case occurs when the check fails due to verifier fault, e.g. being unable to connect to RPC).
Samples are stored in memory. The number of samples is defined by the constant SamplesToConsider, which is closely related to the constant SampleInterval, determining the polling interval. See verifier file for reference.
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.
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 all tests with coverage
sh gencover.shThe 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:
- Do not require Docker and can be run directly:
go test -v <path_to_test>
- Do not require Docker and can be run directly:
- A few tests, related to PMWPaymentStatus attestation type are Docker dependant tests (e.g., tests that access the indexer databases).
Note: These tests include a comment in the test file marking them as Docker-dependent.
- Start Docker manually:
docker compose -f internal/tests/docker/docker-compose.yaml up -d
- Run the test:
go test -v <path_to_test>
- Stop Docker after finishing:
docker compose -f internal/tests/docker/docker-compose.yaml down
- Start Docker manually:
-
Running fuzz tests
Fuzz tests run their seed corpus as regular tests during
go testandgencover.sh. To run actual fuzzing with random inputs:go test ./internal/attestation/tee_availability_check/verifier/ -fuzz FuzzResolveExternalURL -fuzztime 60sAvailable fuzz targets:
FuzzResolveExternalURL,FuzzGetOrFetchCRL,FuzzGetCRLsForToken,FuzzFetchTEEChallengeResult. -
Running load tests
Load tests are gated behind the
loadbuild tag and don't run during normalgo testorgencover.sh:go test -tags load -run TestLoad -v ./internal/attestation/tee_availability_check/verifier/ ./internal/attestation/tee_availability_check/tee_poller/ ./internal/attestation/pmw_multisig_account_configured/xrp/ ./internal/attestation/pmw_payment_status/db/ ./internal/attestation/pmw_payment_status/xrp/ ./internal/attestation/pmw_fee_proof/db/ ./internal/attestation/pmw_fee_proof/xrp/ -
Running stress tests
Stress tests are gated behind the
stressbuild tag. They take longer (~70s) and push beyond normal load:go test -tags stress -run TestStress -v ./internal/attestation/tee_availability_check/verifier/ ./internal/attestation/tee_availability_check/tee_poller/For detailed results, findings, and test parameters, see docs/load-and-stress-tests.md.
- Other
TODOs inside the code and README. - How often should we query GetAllActiveTeeMachines? At the moment, each poll also retrieves GetAllActiveTeeMachines.
- 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: Benchmark and adjust
MaxNonceRange(currently 100). - PMWFeeProof: Should the verifier validate that the requested nonce range falls within the XRP indexer data retention window (~2 weeks), or just let it fail with 422 if data is missing?
- PMWFeeProof: Confirm with FAsset team that the
estimatedFeeformula (pay_maxFee + sum(max(0, reissue_maxFee - pay_maxFee))) is suitable for their fee reconciliation use case.
- When the
TeeAvailabilityCheckverifier is running, poller samples should be monitored via the/poller/teesroute to ensure that timestamps are recent enough, allowing early detection of poller failures.
See docs/SPEC.md for the full technical specification covering architecture, verification flows, error model, and configuration.