This document describes how to benchmark the Token Validation Service at the node level using the Fabric Smart Client (FSC) framework.
The Token Validation Service benchmarks measure the performance of token request validation (including transfers, issues, and auditing) through different architectural layers:
These benchmarks complement the core driver benchmarks by testing the complete validation service layer including FSC integration, network communication, and node orchestration.
The Token Validation Service benchmarks serve several critical purposes:
Panurus comes pre-equipped with test data containing cryptographic parameters and sample token transfers located at:
token/core/zkatdlog/nogh/v1/regression/testdata/zero
This directory includes:
32-BLS12_381_BBS_GURVY/params.txt)<config>/testdata.jsonNote: The test data is already included in the repository. You only need to regenerate it if you want to create custom test cases with different parameters or token configurations. To regenerate test data on demand:
cd token/core/zkatdlog/nogh/v1/regression
go test -run TestRegression -v
The test data is required by all benchmark types (Local, API, gRPC, and Distributed).
Tests token validation directly in-process without any network or API overhead. This establishes the performance baseline.
cd cmd/token_validation_service
GOGC=10000 go test -run ^$ -bench=BenchmarkLocalTokenValidation -benchtime=30s -count=5 -cpu=1,4,8,16,32,64
Parameters:
GOGC=10000: Reduces garbage collection frequency for more stable measurements-benchtime=30s: Run each benchmark for 30 seconds-count=5: Repeat each benchmark 5 times for statistical significance-cpu=1,4,8,16,32,64: Test with different numbers of parallel goroutinesTests token validation through FSC’s View API on a single node. Measures API overhead compared to direct validation.
cd cmd/token_validation_service
GC=10000 go test -bench=BenchmarkAPI -benchtime=30s
What it does:
Tests token validation through gRPC client-server architecture on localhost. Measures network serialization overhead.
cd cmd/token_validation_service
GOGC=10000 go test -bench=BenchmarkAPIGRPC -benchtime=30s -count=5 -cpu=32 -numConn=1,2,4,8
Parameters:
-numConn=1,2,4,8: Test with different numbers of gRPC client connectionsWhat it does:
To setup AWS EC2 nodes See: AWS Benchmark 2 Machines
For realistic deployment testing with separate client and server machines:
Architecture:
Setup:
known_hosts (If not already connected)cd cmd/token_validation_service
GOGC=10000 go run ./server/
Wait until you see the output:
Running fscnode test-node
[Note: We set GOGC to 10K but you don’t have to]
Rsync for this:
```bash
cd cmd/token_validation_servicersync -avz
Note: Make sure full path and server name are correct
4. Replace the IP (or full name DNS can resolve) to the Server IP in the client out folder:
```bash
sed 's#127.0.0.1#123.456.789#g' ./out/testdata/fsc/nodes/test-node.0/client-config.yaml -i
GOGC=10000 go run ./client/ -benchtime=30s -count=5 -workloads=token-validation-service -cpu=1,2,4,8,16,32,48,64 -numConn=1,2,4,8 2>&1 | tee out.txt &
This setup is ideal for:
python -m venv .venv
source .venv/bin/activate
pip install streamlit pandas plotly
Place the results in .txt files in a folder called bench.
Run:
streamlit run cmd/benchmarking/plotly_plot_node.py
They both already have each-others SSH Keys, so I don’t need to do it again.
On dectrust2, Server Runs:
cd cmd/token_validation_service
GOGC=10000 go run ./server/
I wait to see:
Running fscnode test-node
On dectrust1:
cd ~/effi/panurus/cmd/token_validation_service
rsync -avz root@dectrust2.vpc.cloud9.ibm.com:/root/effi/panurus/cmd/token_validation_service/out/ ./out
sed 's#127.0.0.1#dectrust1.vpc.cloud9.ibm.com#g' ./out/testdata/fsc/nodes/test-node.0/client-config.yaml -i
GOGC=10000 nohup go run ./client/ -benchtime=30s -count=5 -workloads=zkp -cpu=1,2,4,8,16,32 -numConn=1,2,4,8 2>&1 | tee example-2node.txt &
I also run gRPC benchmark without the 2 node setup:
GOGC=10000 go test -bench=BenchmarkAPIGRPC -benchtime=30s -count=5 -cpu=32 -numConn=1,2,4,8 | tee example-grpc.txt
I now move the outputs to bench folder and run the visualisation:
mv example-2node.txt bench
mv example-grpc.txt
(Optional) I setup python venv:
python -m venv .venv
source .venv/bin/activate
pip install streamlit pandas
Now I can run the visualisation:
streamlit run cmd/benchmarking/plotly_plot_node.py
Each benchmark reports:
BenchmarkLocalTokenValidation/out-tokens=2in-tokens=2-32 1000 30000000 ns/op 33333 TPS
Interpretation:
-cpu=32)The benchmarks are agnostic to the range-proof system used by the token transfers:
the proof type is baked into the public parameters (params.txt) of whichever test-root
you point at. Two corpora ship under testdata/zero:
| Range-proof system | Test-root (relative to cmd/token_validation_service) |
|---|---|
| IPA / bulletproof (default) | ../../token/core/zkatdlog/nogh/v1/regression/testdata/zero/32-BLS12_381_BBS_GURVY |
| CSP | ../../token/core/zkatdlog/nogh/v1/regression/testdata/zero/csp/32-BLS12_381_BBS_GURVY |
Every benchmark (BenchmarkLocalTokenValidation, BenchmarkAPI, BenchmarkAPIGRPC)
and the standalone client accept a -testRoot flag that overrides the corpus. When
omitted it defaults to the IPA test-root above. To benchmark CSP proofs instead,
pass the csp test-root:
cd cmd/token_validation_service
# Local baseline against CSP proofs
GOGC=10000 go test -run ^$ -bench=BenchmarkLocalTokenValidation -benchtime=30s -cpu=1,4,8,16,32 \
-testRoot=../../token/core/zkatdlog/nogh/v1/regression/testdata/zero/csp/32-BLS12_381_BBS_GURVY
# API benchmark against CSP proofs
GOGC=10000 go test -run ^$ -bench=BenchmarkAPI -benchtime=30s \
-testRoot=../../token/core/zkatdlog/nogh/v1/regression/testdata/zero/csp/32-BLS12_381_BBS_GURVY
# gRPC benchmark against CSP proofs
GOGC=10000 go test -run ^$ -bench=BenchmarkAPIGRPC -benchtime=30s -cpu=32 -numConn=1,2,4,8 \
-testRoot=../../token/core/zkatdlog/nogh/v1/regression/testdata/zero/csp/32-BLS12_381_BBS_GURVY
# Standalone client (distributed benchmark) against CSP proofs
GOGC=10000 go run ./client/ -testRoot=../../token/core/zkatdlog/nogh/v1/regression/testdata/zero/csp/32-BLS12_381_BBS_GURVY
Swap 32-BLS12_381_BBS_GURVY for another configuration (32-BN254,
64-BLS12_381_BBS_GURVY, 64-BN254) to change the curve/bit-length.
Regenerating the CSP corpus (only needed for custom parameters; the data ships in the repo):
cd token/core/zkatdlog/nogh/v1/regression/testdata/zero/generator
go run . -proof_type=csp -bits=32,64 -curves=BN254,BLS12_381_BBS_GURVY -num_inputs=1,2 -num_outputs=1,2
The -proof_type flag selects the system (csp for CSP; omit it, or use bf/bulletproof,
for the IPA default). CSP output is written to the separate zero/csp/ subtree so it never
overwrites the IPA vectors.