{ } rg-gateway v1.0.0
Documentation

Technical Reference

Reason codes, share event schema, configuration reference, protocol contract, and security boundaries.

Gateway Reason Codes

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

Verdict Reason Codes

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

Share Event Reference

Two-event lifecycle: share_accepted on receipt, share_forward_result on upstream response.

share_accepted

Emitted immediately when share is accepted by gateway. One event per valid share submission.

Field Type Description
share_id SHA256 hash Proof-of-work deduplication key; stable identifier for this share
event_id SHA256 hash Event attribution and integrity key; joins share_accepted to share_forward_result
channel_id u32 SV2 channel ID assigned to this miner connection
job_id u32 Job ID from active template cache
worker_id String Authenticated worker identity from SV2 connection
validation_level String Depth of validation performed: "basic", "full", or "enhanced"
sv2_response "success" | "error" Whether share was accepted (success) or rejected (error)
reason_code GatewayReason Machine-readable code for the decision; present if sv2_response = "error"
fee_tier String Configured fee tier from policy (e.g., "low", "mid", "high")
difficulty_target f64 Channel difficulty at time of submission
timestamp_ms u64 Unix timestamp in milliseconds at gateway receipt
gateway_instance_id String Identifier for the gateway process handling this share

share_forward_result

Emitted after upstream HTTP response is received (or timeout occurs). One event per share_accepted with sv2_response = "success".

Field Type Description
share_id SHA256 hash Same share_id from corresponding share_accepted event
event_id SHA256 hash Same event_id from corresponding share_accepted; join key
forwarded bool Whether share was successfully transmitted to upstream (true = sent, false = queue dropped)
upstream_accepted Option<bool> Upstream accept field from JSON response; null if connection failed
upstream_http_status Option<u16> HTTP status code from upstream response; null if transport error
upstream_error Option<String> Error message from upstream response; null if accepted or transport error
reason_code Option<GatewayReason> Gateway reason if forwarded=false (queue drop, timeout, etc.); null if forwarded=true
timestamp_ms u64 Unix timestamp in milliseconds at result recording
1:1 join invariant: Every share_accepted with sv2_response = "success" produces exactly one share_forward_result. The adapter blocks on channel capacity rather than dropping results.

Configuration Reference

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
share_upstream_url (required) HTTP endpoint for share submissions (pool backend POST target)
share_upstream_secret (required) HMAC-SHA256 secret for signing share POST requests
share_upstream_retries 2 Number of retries on transient upstream failures
share_forward_queue_size 50000 Maximum pending shares in forward queue
share_forward_max_in_flight 256 Maximum concurrent upstream requests
share_forward_queue_drop_policy drop_new Policy on queue overflow: "drop_new" or "drop_old"
share_dedup_window_size 10000 Deduplication window size (number of unique share_ids to track)
initial_difficulty 1.0 Initial share difficulty for new channels
share_upstream_submit_timeout_ms 2000 Timeout for individual upstream share submission
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)

Security Boundaries

Design invariants and operational constraints.

What it is

  • A miner-facing gateway that verifies templates in real-time
  • Noise NX encrypted transport with certificate binding
  • Deterministic fail-closed prevhash switching with 50ms timeout
  • Machine-readable reason codes for every decision
  • Two-event share lifecycle with HMAC-SHA256 signing

What it is not

  • A pool backend or share accounting system
  • A replacement for upstream policy enforcement
  • A DDoS mitigation appliance (no rate limiting beyond peer quotas)
  • A full peer-to-peer SV2 implementation
  • A substitute for operator vigilance and monitoring

Operational guidance

  • Always run in shadow mode first to establish trust
  • Monitor verifier latency and uptime continuously
  • Audit share_forward_result for upstream rejections
  • Rotate http_api_key regularly and keep secure
  • Use TLS for HTTP endpoints in production
⚠ Critical: Do not expose /gateway/events or /metrics to untrusted networks. Set http_api_key in production. Both endpoints require authentication to prevent information leakage.

Ready to integrate?

Start with Observe mode to audit your templates. Move to Inline when you're confident in your policy.