Run a witness
witness-node is the signing service for one witness. It holds one Ed25519
private key or BLS12-381 secret key and answers gateway signing requests. It is
pre-1.0 and unaudited; run it only on a host and network path you control.
Build and generate a key
Build the binary from the workspace root:
cargo build --release -p witness-node
Generate an Ed25519 keypair with the repository's key generator:
target/release/witness-node --generate-key
For a BLS keypair:
target/release/witness-node --generate-key --bls
Keep the private key secret. Give the public key and witness ID to the network
coordinator; do not give the private key to the gateway or publish the
witness.json file.
Configuration
The default configuration path is witness.json. The node configuration has
these operational fields:
{
"id": "witness-1",
"signature_scheme": "ed25519",
"private_key": "<32-byte-hex-private-key>",
"host": "127.0.0.1",
"port": 3000,
"network_id": "my-network",
"signing_auth_token": "<high-entropy-secret>",
"max_clock_skew": 300
}
private_key is a 32-byte Ed25519 seed or BLS secret key, according to the
declared scheme. signing_auth_token is required and must be non-empty.
max_clock_skew defaults to 300 seconds. A
previous_signing_auth_token may be present during the implementation's
token-rotation transition; this is credential overlap, not a general revoke
mechanism.
The node validates the key and token at startup. Keep the configuration file access-controlled: the private key and bearer tokens are operational secrets, even though the process zeroizes those string fields when its configuration is dropped.
Start and bind
Start with the config defaults:
target/release/witness-node --config /etc/witness/witness.json
Override the bind host or port only when the network design requires it:
target/release/witness-node \
--config /etc/witness/witness.json \
--host 127.0.0.1 \
--port 3000
The node speaks plain HTTP and defaults to loopback. Do not expose /v1/sign
to the public internet. Put the node on a trusted/private path accessible to
the configured gateway, or apply an equivalent network boundary. The gateway
must send the matching bearer token.
Endpoints and checks
GET /healthis a liveness probe.GET /v1/inforeports the node ID, public key, and network ID.POST /v1/signrequiresAuthorization: Bearer <signing_auth_token>.
Authentication is checked before the node's defense-in-depth limit of 60 sign
requests per IP per minute. A signing request is rejected when its timestamp
exceeds max_clock_skew or its attestation network ID differs from the node's
configured network_id.
Keep clocks synchronized across gateways and witnesses. A valid response from
/health proves liveness only; it does not prove that a witness is honest or
that a threshold can be met.