Reason codes, share event schema, configuration reference, protocol contract, and security boundaries.
34 machine-readable codes for every gateway decision. Filter by category below.
| Code | Category | Description |
|---|---|---|
noise_handshake_failed |
Transport | Noise NX handshake did not complete (crypto failure or incompatible params) |
noise_handshake_timeout |
Transport | Handshake exceeded handshake_timeout_ms |
unsupported_protocol_version |
Transport | Miner offered unsupported SV2 protocol version |
connection_rate_limited |
Transport | Inbound connections exceeded per-IP rate limit |
frame_decode_error |
Framing | SV2 binary frame could not be decoded |
frame_too_large |
Framing | Frame exceeded maximum allowed size |
peer_quota_exceeded |
Framing | Peer exceeded rate_limit_messages_per_sec or rate_limit_bytes_per_sec |
internal_framing_error |
Framing | Internal NDJSON message could not be parsed |
internal_line_too_large |
Framing | Internal message exceeded MAX_INTERNAL_LINE_BYTES (1 MiB) |
internal_version_mismatch |
Framing | Internal msg_type version not supported |
internal_unknown_msg_flood |
Framing | Unknown msg_type exceeded MAX_UNKNOWN_MSG_TYPE_PER_MINUTE (60) |
miner_unauthorized |
Auth | Worker identity not in allowlist and no prefix match |
identity_prefix_unmatched |
Auth | Worker identity did not match any prefix_map entry |
identity_too_long |
Auth | user_identity exceeded max_worker_id_bytes (128) |
channel_open_rejected |
Channel | OpenMiningChannel denied (mapped to SV2 error) |
channel_limit_exceeded |
Channel | Connection exceeded max_channels_per_connection |
invalid_channel_id |
Channel | Share referenced a channel_id not assigned to this connection |
extended_channel_unsupported |
Channel | Miner requested extended channel (V1.0.0 supports standard only) |
prevhash_switch_timeout |
Job | Verdict did not arrive within prevhash_verdict_timeout_ms and stale hold expired |
prevhash_verdict_rejected |
Job | Verifier rejected the prevhash template (inline mode gates it) |
template_cache_miss |
Job | Template referenced by share not found in LRU cache |
stale_job_submission |
Job | Share referenced a job_id from a superseded template |
upstream_unavailable |
Job | Template source (template-manager) not reachable |
share_replay_detected |
Share | share_id already seen in dedup window |
share_difficulty_below_target |
Share | Share hash did not meet channel difficulty |
share_invalid_job_id |
Share | job_id not in active job table |
share_invalid_nonce |
Share | Nonce validation failed |
version_bit_violation |
Share | version_bits outside BIP320 general purpose mask |
ntime_out_of_range |
Share | ntime outside allowed bounds |
share_forward_failed |
Share | HTTP POST to share upstream failed (transport) |
share_upstream_rejected |
Share | Upstream returned accepted=false |
share_dropped_queue_full |
Share | Forward queue at capacity, share dropped per policy |
share_evicted_from_queue |
Share | Share evicted from queue under drop_old policy |
share_rate_limited |
Share | Per-connection share rate exceeded limit |
15 verdicts emitted by the template verifier. Used in template_verdict events and gateway disconnects.
| Code | Category | Description |
|---|---|---|
ok |
Verdict | Template accepted by verifier |
avg_fee_below_minimum |
Fees | Average fee per vByte below configured minimum |
total_fees_below_minimum |
Fees | Total coinbase rewards below policy threshold |
coinbase_value_zero_rejected |
Template | Coinbase output value is zero and policy rejects it |
tx_count_exceeded |
Template | Transaction count exceeds policy maximum |
prev_hash_len_mismatch |
Template | Previous block hash length does not match expected value |
invalid_prev_hash |
Template | Previous block hash does not reference valid chain |
protocol_version_mismatch |
Protocol | Block version or protocol level not supported |
empty_template_rejected |
Template | Template contains no transactions and policy rejects it |
policy_load_error |
System | Verifier could not load or parse policy configuration |
mempool_backend_unavailable |
System | Connection to mempool data source lost or unavailable |
internal_error |
System | Internal verifier error or panic |
weight_ratio_exceeded |
Safety | Transaction weight exceeds allowed ratio to block size |
template_stale |
Safety | Template exceeds max_template_age_ms without update |
sigops_budget_warning |
Safety | Cumulative sigops budget near capacity |
coinbase_sigops_abnormal |
Safety | Coinbase script sigops count is abnormally high |
51 TOML configuration keys across six categories. All values can be overridden by environment variables.
| Key | Default | Notes |
|---|---|---|
mode |
(required) | Deployment mode: "shadow", "observe", or "inline" |
listen_addr |
0.0.0.0:3333 | Socket address for inbound miner connections |
http_addr |
127.0.0.1:8082 | Socket address for HTTP API and metrics (/gateway/events, /metrics) |
verifier_addr |
127.0.0.1:5001 | TCP address of pool-verifier for template verdicts |
verifier_http_url |
(derived) | HTTP endpoint for verifier GET /status; defaults to http://verifier_addr/status |
upstream_url |
(required) | URL of job server (template-manager or bitcoind RPC) |
upstream_failure_policy |
(required) | Action on upstream disconnect: "fail_closed" or "fail_open" |
| Key | Default | Notes |
|---|---|---|
noise_key_file |
(required) | Path to gateway's Noise static private key (32 bytes, hex encoded) |
noise_cert_file |
(required) | Path to gateway's certificate (for miner identity binding) |
authority_public_key_file |
(required) | Path to authorized public key for Noise handshake validation |
http_api_key |
(optional) | API key for HTTP endpoints; if set, all requests must include X-API-Key header |
http_tls_cert_file |
(optional) | Path to TLS certificate for HTTPS HTTP server |
http_tls_key_file |
(optional) | Path to TLS private key for HTTPS HTTP server |
| Key | Default | Notes |
|---|---|---|
upstream_poll_interval_ms |
3000 | Milliseconds between upstream template polls |
upstream_health_timeout_ms |
5000 | Timeout for upstream health check request |
upstream_stale_max_ms |
30000 | Maximum age of template before marking upstream unavailable |
prevhash_verdict_timeout_ms |
50 | Milliseconds to wait for verifier verdict on prevhash change |
prevhash_stale_hold_ms |
5000 | Milliseconds to hold stale job before disconnect on prevhash timeout |
health_probe_interval_ms |
30000 | Milliseconds between verifier health probes |
verifier_heartbeat_interval_ms |
15000 | Milliseconds between heartbeat messages to verifier |
max_template_age_ms |
60000 | Maximum age of cached template before VerdictReason: template_stale |
template_cache_size |
64 | Maximum number of templates to retain in LRU cache |
max_future_templates |
2 | Maximum number of unverified future templates allowed in-flight |
| Key | Default | Notes |
|---|---|---|
auth.mode |
(required) | Authentication strategy: "allowlist", "prefix_map", or "open" |
auth.allowlist |
(optional) | Array of allowed worker identities (for allowlist mode) |
auth.prefix_map |
(optional) | Map of identity prefixes to policies (for prefix_map mode) |
max_worker_id_bytes |
128 | Maximum allowed length of worker identity string |
| Environment Variable | Purpose |
|---|---|
VELDRA_ALLOW_DROP_OLD_INLINE |
Allows drop_old share queue policy in inline mode (default: forbidden for safety) |
VELDRA_GATEWAY_ALLOW_OPEN_AUTH |
Permits auth.mode = "open" without allowlist/prefix_map (default: forbidden) |
VELDRA_ALLOW_NO_API_KEY |
Allows http_addr to be exposed without http_api_key authentication (default: forbidden) |
VELDRA_ALLOW_PLAINTEXT |
Permits miner connections without Noise encryption (default: forbidden) |
VELDRA_ALLOW_INSECURE_HTTP_UPSTREAM |
Allows upstream_url to use http:// instead of https:// (default: forbidden) |
VELDRA_ALLOW_NO_SHARE_UPSTREAM_READY_INLINE |
Permits inline mode when share upstream is not reachable at startup (default: forbidden) |
Design invariants and operational constraints.
/gateway/events or /metrics to untrusted networks.
Set http_api_key in production. Both endpoints require authentication to prevent information leakage.
Start with Observe mode to audit your templates. Move to Inline when you're confident in your policy.