-
Notifications
You must be signed in to change notification settings - Fork 6
Description
gRPC API Testing Guide with grpcurl
This guide provides comprehensive examples for testing all gRPC services in the Fabric-X Common API using grpcurl. Examples are provided for three security configurations: no TLS, TLS, and mutual TLS (mTLS).
Prerequisites
Install grpcurl:
# macOS
brew install grpcurl
# Linux
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
# Or download from: https://github.com/fullstorydev/grpcurl/releasesCertificate Setup
For TLS and mTLS examples, you'll need certificates. Generate test certificates using:
# Generate CA certificate
openssl req -x509 -newkey rsa:4096 -keyout ca-key.pem -out ca-cert.pem -days 365 -nodes -subj "/CN=Test CA"
# Generate server certificate
openssl req -newkey rsa:4096 -keyout server-key.pem -out server-csr.pem -nodes -subj "/CN=localhost"
openssl x509 -req -in server-csr.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 365
# Generate client certificate (for mTLS)
openssl req -newkey rsa:4096 -keyout client-key.pem -out client-csr.pem -nodes -subj "/CN=client"
openssl x509 -req -in client-csr.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -days 365Environment Variables
Set these variables for easier command execution:
# Server endpoint
export SERVER_HOST="localhost:9443"
# Certificate paths (adjust as needed)
export CA_CERT="path/to/ca-cert.pem"
export CLIENT_CERT="path/to/client-cert.pem"
export CLIENT_KEY="path/to/client-key.pem"
# Proto import path (adjust to your fabric-x-common location)
export PROTO_PATH="/path/to/fabric-x-common"1. BlockQueryService (committerpb)
Service Definition: committerpb.BlockQueryService
Proto File: api/committerpb/block_query.proto
This service provides read-only access to the blockchain ledger, allowing queries for blockchain information, blocks, and transactions.
1.1 GetBlockchainInfo
Retrieves information about the blockchain (height, current block hash, previous block hash).
No TLS
grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/block_query.proto \
${SERVER_HOST} \
committerpb.BlockQueryService/GetBlockchainInfoTLS
grpcurl \
-cacert ${CA_CERT} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/block_query.proto \
${SERVER_HOST} \
committerpb.BlockQueryService/GetBlockchainInfomTLS
grpcurl \
-cacert ${CA_CERT} \
-cert ${CLIENT_CERT} \
-key ${CLIENT_KEY} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/block_query.proto \
${SERVER_HOST} \
committerpb.BlockQueryService/GetBlockchainInfo1.2 GetBlockByNumber
Retrieves a specific block by its block number.
No TLS
grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/block_query.proto \
-d '{"number": 0}' \
${SERVER_HOST} \
committerpb.BlockQueryService/GetBlockByNumberTLS
grpcurl \
-cacert ${CA_CERT} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/block_query.proto \
-d '{"number": 0}' \
${SERVER_HOST} \
committerpb.BlockQueryService/GetBlockByNumbermTLS
grpcurl \
-cacert ${CA_CERT} \
-cert ${CLIENT_CERT} \
-key ${CLIENT_KEY} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/block_query.proto \
-d '{"number": 0}' \
${SERVER_HOST} \
committerpb.BlockQueryService/GetBlockByNumber1.3 GetBlockByTxID
Retrieves the block containing a specific transaction ID.
No TLS
grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/block_query.proto \
-d '{"tx_id": "your-transaction-id-here"}' \
${SERVER_HOST} \
committerpb.BlockQueryService/GetBlockByTxIDTLS
grpcurl \
-cacert ${CA_CERT} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/block_query.proto \
-d '{"tx_id": "your-transaction-id-here"}' \
${SERVER_HOST} \
committerpb.BlockQueryService/GetBlockByTxIDmTLS
grpcurl \
-cacert ${CA_CERT} \
-cert ${CLIENT_CERT} \
-key ${CLIENT_KEY} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/block_query.proto \
-d '{"tx_id": "your-transaction-id-here"}' \
${SERVER_HOST} \
committerpb.BlockQueryService/GetBlockByTxID1.4 GetTxByID
Retrieves a specific transaction envelope by its transaction ID.
No TLS
grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/block_query.proto \
-d '{"tx_id": "your-transaction-id-here"}' \
${SERVER_HOST} \
committerpb.BlockQueryService/GetTxByIDTLS
grpcurl \
-cacert ${CA_CERT} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/block_query.proto \
-d '{"tx_id": "your-transaction-id-here"}' \
${SERVER_HOST} \
committerpb.BlockQueryService/GetTxByIDmTLS
grpcurl \
-cacert ${CA_CERT} \
-cert ${CLIENT_CERT} \
-key ${CLIENT_KEY} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/block_query.proto \
-d '{"tx_id": "your-transaction-id-here"}' \
${SERVER_HOST} \
committerpb.BlockQueryService/GetTxByID2. Notifier Service (committerpb)
Service Definition: committerpb.Notifier
Proto File: api/committerpb/notify.proto
This service provides a bidirectional streaming API for subscribing to ledger events and receiving asynchronous notifications about transaction statuses.
2.1 OpenNotificationStream
Opens a bidirectional stream for transaction status notifications. This is a streaming RPC where the client sends subscription requests and receives notifications.
Note: Bidirectional streaming requires interactive mode or scripting. Below are examples for both approaches.
No TLS (Interactive)
grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/notify.proto \
-d @ \
${SERVER_HOST} \
committerpb.Notifier/OpenNotificationStreamThen input JSON requests interactively:
{"tx_status_request": {"tx_ids": ["tx-id-1", "tx-id-2"]}, "timeout": {"seconds": 30}}TLS (Interactive)
grpcurl \
-cacert ${CA_CERT} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/notify.proto \
-d @ \
${SERVER_HOST} \
committerpb.Notifier/OpenNotificationStreammTLS (Interactive)
grpcurl \
-cacert ${CA_CERT} \
-cert ${CLIENT_CERT} \
-key ${CLIENT_KEY} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/notify.proto \
-d @ \
${SERVER_HOST} \
committerpb.Notifier/OpenNotificationStreamScripted Example (No TLS)
# Create a file with subscription requests
cat > notify_requests.json << EOF
{"tx_status_request": {"tx_ids": ["tx-id-1"]}, "timeout": {"seconds": 30}}
{"tx_status_request": {"tx_ids": ["tx-id-2"]}, "timeout": {"seconds": 30}}
EOF
# Send requests via pipe
cat notify_requests.json | grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/notify.proto \
-d @ \
${SERVER_HOST} \
committerpb.Notifier/OpenNotificationStreamScripted Example (TLS)
cat notify_requests.json | grpcurl \
-cacert ${CA_CERT} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/notify.proto \
-d @ \
${SERVER_HOST} \
committerpb.Notifier/OpenNotificationStreamScripted Example (mTLS)
cat notify_requests.json | grpcurl \
-cacert ${CA_CERT} \
-cert ${CLIENT_CERT} \
-key ${CLIENT_KEY} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/notify.proto \
-d @ \
${SERVER_HOST} \
committerpb.Notifier/OpenNotificationStream3. QueryService (committerpb)
Service Definition: committerpb.QueryService
Proto File: api/committerpb/query.proto
This service provides query capabilities for reading state data, managing views (database snapshots), and retrieving configuration and transaction status information.
3.1 GetRows
Queries key-value pairs from specified namespaces, optionally within a view context.
No TLS
grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
-d '{
"namespaces": [
{
"ns_id": "namespace1",
"keys": ["a2V5MQ==", "a2V5Mg=="]
}
]
}' \
${SERVER_HOST} \
committerpb.QueryService/GetRowsNote: Keys must be base64-encoded. Example: echo -n "key1" | base64 produces a2V5MQ==
TLS
grpcurl \
-cacert ${CA_CERT} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
-d '{
"namespaces": [
{
"ns_id": "namespace1",
"keys": ["a2V5MQ==", "a2V5Mg=="]
}
]
}' \
${SERVER_HOST} \
committerpb.QueryService/GetRowsmTLS
grpcurl \
-cacert ${CA_CERT} \
-cert ${CLIENT_CERT} \
-key ${CLIENT_KEY} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
-d '{
"namespaces": [
{
"ns_id": "namespace1",
"keys": ["a2V5MQ==", "a2V5Mg=="]
}
]
}' \
${SERVER_HOST} \
committerpb.QueryService/GetRowsWith View Context
# First create a view (see BeginView below), then use its ID
grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
-d '{
"view": {"id": "view-id-from-begin-view"},
"namespaces": [
{
"ns_id": "namespace1",
"keys": ["a2V5MQ=="]
}
]
}' \
${SERVER_HOST} \
committerpb.QueryService/GetRows3.2 BeginView
Creates a new view (database snapshot) with specified isolation level and parameters.
No TLS
grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
-d '{
"iso_level": "SERIALIZABLE",
"non_deferrable": false,
"timeout_milliseconds": 30000
}' \
${SERVER_HOST} \
committerpb.QueryService/BeginViewIsolation Levels:
ISO_LEVEL_UNSPECIFIED(defaults to SERIALIZABLE)SERIALIZABLEREPEATABLE_READREAD_COMMITTEDREAD_UNCOMMITTED
TLS
grpcurl \
-cacert ${CA_CERT} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
-d '{
"iso_level": "SERIALIZABLE",
"non_deferrable": false,
"timeout_milliseconds": 30000
}' \
${SERVER_HOST} \
committerpb.QueryService/BeginViewmTLS
grpcurl \
-cacert ${CA_CERT} \
-cert ${CLIENT_CERT} \
-key ${CLIENT_KEY} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
-d '{
"iso_level": "REPEATABLE_READ",
"non_deferrable": true,
"timeout_milliseconds": 60000
}' \
${SERVER_HOST} \
committerpb.QueryService/BeginView3.3 EndView
Closes an active view and releases associated resources.
No TLS
grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
-d '{"id": "view-id-from-begin-view"}' \
${SERVER_HOST} \
committerpb.QueryService/EndViewTLS
grpcurl \
-cacert ${CA_CERT} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
-d '{"id": "view-id-from-begin-view"}' \
${SERVER_HOST} \
committerpb.QueryService/EndViewmTLS
grpcurl \
-cacert ${CA_CERT} \
-cert ${CLIENT_CERT} \
-key ${CLIENT_KEY} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
-d '{"id": "view-id-from-begin-view"}' \
${SERVER_HOST} \
committerpb.QueryService/EndView3.4 GetNamespacePolicies
Retrieves the policies for all namespaces.
No TLS
grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
${SERVER_HOST} \
committerpb.QueryService/GetNamespacePoliciesTLS
grpcurl \
-cacert ${CA_CERT} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
${SERVER_HOST} \
committerpb.QueryService/GetNamespacePoliciesmTLS
grpcurl \
-cacert ${CA_CERT} \
-cert ${CLIENT_CERT} \
-key ${CLIENT_KEY} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
${SERVER_HOST} \
committerpb.QueryService/GetNamespacePolicies3.5 GetConfigTransaction
Retrieves the current configuration transaction envelope.
No TLS
grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
${SERVER_HOST} \
committerpb.QueryService/GetConfigTransactionTLS
grpcurl \
-cacert ${CA_CERT} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
${SERVER_HOST} \
committerpb.QueryService/GetConfigTransactionmTLS
grpcurl \
-cacert ${CA_CERT} \
-cert ${CLIENT_CERT} \
-key ${CLIENT_KEY} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
${SERVER_HOST} \
committerpb.QueryService/GetConfigTransaction3.6 GetTransactionStatus
Queries the status of one or more transactions, optionally within a view context.
No TLS
grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
-d '{
"tx_ids": ["tx-id-1", "tx-id-2", "tx-id-3"]
}' \
${SERVER_HOST} \
committerpb.QueryService/GetTransactionStatusTLS
grpcurl \
-cacert ${CA_CERT} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
-d '{
"tx_ids": ["tx-id-1", "tx-id-2"]
}' \
${SERVER_HOST} \
committerpb.QueryService/GetTransactionStatusmTLS
grpcurl \
-cacert ${CA_CERT} \
-cert ${CLIENT_CERT} \
-key ${CLIENT_KEY} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
-d '{
"tx_ids": ["tx-id-1"]
}' \
${SERVER_HOST} \
committerpb.QueryService/GetTransactionStatusWith View Context
grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
-d '{
"view": {"id": "view-id-from-begin-view"},
"tx_ids": ["tx-id-1", "tx-id-2"]
}' \
${SERVER_HOST} \
committerpb.QueryService/GetTransactionStatusService Discovery
List all available services on a server:
No TLS
grpcurl -plaintext ${SERVER_HOST} listTLS
grpcurl -cacert ${CA_CERT} ${SERVER_HOST} listmTLS
grpcurl -cacert ${CA_CERT} -cert ${CLIENT_CERT} -key ${CLIENT_KEY} ${SERVER_HOST} listDescribe a specific service:
No TLS
grpcurl -plaintext \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
${SERVER_HOST} \
describe committerpb.QueryServiceTLS
grpcurl \
-cacert ${CA_CERT} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
${SERVER_HOST} \
describe committerpb.QueryServicemTLS
grpcurl \
-cacert ${CA_CERT} \
-cert ${CLIENT_CERT} \
-key ${CLIENT_KEY} \
-import-path ${PROTO_PATH} \
-proto api/committerpb/query.proto \
${SERVER_HOST} \
describe committerpb.QueryServiceCommon Options
Verbose Output
Add -v or -vv for verbose output:
grpcurl -plaintext -v ${SERVER_HOST} committerpb.QueryService/GetNamespacePoliciesCustom Headers
Add custom metadata headers:
grpcurl -plaintext \
-H "authorization: Bearer token123" \
-H "x-custom-header: value" \
${SERVER_HOST} \
committerpb.QueryService/GetNamespacePoliciesTimeout
Set request timeout:
grpcurl -plaintext \
-max-time 30 \
${SERVER_HOST} \
committerpb.QueryService/GetNamespacePoliciesOutput Formatting
Format output with jq:
grpcurl -plaintext ${SERVER_HOST} \
committerpb.BlockQueryService/GetBlockchainInfo | jq .Troubleshooting
Connection Refused
- Verify the server is running:
netstat -an | grep 9443 - Check firewall rules
- Verify the correct host and port
Certificate Errors
- Ensure certificate paths are correct
- Verify certificate validity:
openssl x509 -in ${CA_CERT} -text -noout - Check certificate chain:
openssl verify -CAfile ${CA_CERT} ${CLIENT_CERT} - For self-signed certificates, ensure the CA cert is properly specified
Proto Import Errors
- Verify
PROTO_PATHpoints to the fabric-x-common root directory - Ensure all proto dependencies are available
- Check that proto files haven't been modified
Authentication Errors
- For mTLS, verify both client cert and key are provided
- Ensure client certificate is signed by the CA trusted by the server
- Check that the certificate hasn't expired
Invalid Argument Errors
- Validate JSON syntax:
echo '{"key": "value"}' | jq . - Ensure field names match proto definitions exactly (case-sensitive)
- Verify data types (strings, numbers, booleans)
- For bytes fields, use base64 encoding
Additional Resources
Summary of Services
| Service | Proto File | RPCs | Description |
|---|---|---|---|
| BlockQueryService | committerpb/block_query.proto | 4 | Read-only blockchain queries |
| Notifier | committerpb/notify.proto | 1 (streaming) | Transaction status notifications |
| QueryService | committerpb/query.proto | 6 | State queries and view management |
Total: 3 services, 11 RPC methods (including 1 bidirectional streaming)