Skip to content

BaumerCrypto/digidollar-oracle-tools

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

84 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

digidollar-oracle-tools

Operator tools and monitoring scripts for DigiByte DigiDollar Oracle nodes.

Maintained by digibyte-maxi (Oracle Slot 17) β€” see contact at the bottom.


What's in this repo

File Purpose
oracle-monitor.sh Bash health monitor v2.5.4 β€” 12 checks (daemon, oracle, chain sync, peers, price freshness, consensus status, disk, memory, swap pressure, version, NTP, quorum margin). Quorum tracking via getdigidollardeploymentinfo + getoracles with MuSig2 session health. Counts online oracles by heartbeat (stable across round transitions). Anti-flap: cooldown timer + hysteresis buffer prevent alert spam during volatile periods. --config /path for dual-instance monitoring (testnet + mainnet). DigiDollar BIP9 pre-activation guard downgrades oracle checks to standby INFO before activation. Auto-detects either digibyted (headless) or digibyte-qt (Qt wallet) so operators running either binary get correct alerts. Discord webhook alerts with red/yellow/green embeds, NETWORK_LABEL in card titles, footer version stamp. External config file, --dry-run mode, jq-based JSON parsing. State files prevent repeat alerts.
oracle-network-status.sh Gitter network status bot v1.5 β€” posts automated oracle network health summaries to the DigiDollar Gitter channel every 12 hours via Matrix API. Network label in header (auto-detected or config override). Reports: fresh heartbeats, quorum health, consensus price, MuSig2 session, BIP9 activation, last bundle signers, software version adoption, stale/inactive oracle list with @ mention notifications. --config /path flag for dual-instance monitoring (testnet + mainnet). Bot account: @digidollar-oracle-bot:matrix.org.
oracle-roster.template Template for the oracle-to-Gitter-handle mapping file used by the @ mention feature. Copy to ~/.oracle-monitor/oracle-roster.conf and populate with real Matrix IDs. The populated file stays on VPS only β€” never push to GitHub.
config.template Configuration template for oracle-monitor.sh and oracle-network-status.sh. Copy to ~/.oracle-monitor/config and set your oracle ID, webhook URL, alert thresholds, quorum margin thresholds, anti-flap settings, network label, and Matrix API credentials for the Gitter bot. Both scripts work without it using built-in defaults.
ORACLE_SETUP_QUICKSTART.md Quick-start checklist for new oracle operators. Covers download, config, key generation, and posting to Gitter.
ORACLE_SETUP_TUTORIAL.md Full step-by-step tutorial for all platforms (Linux, Windows, macOS). Posted by shenger in the DigiDollar Gitter community.
ORACLE_HARDENING_GUIDE.md VPS security hardening guide v1.4.1 β€” SSH, UFW, Fail2Ban, kernel hardening, systemd, resource isolation and OOM protection. Step-by-step, based on my live oracle setup.
HOME_ORACLE_HARDENING_GUIDE.md Home network security hardening guide β€” Linux, Windows, macOS. Three tiers (Essential, Recommended, Advanced). Covers firewall, port forwarding, NTP, router hardening, UPS, VLANs, WireGuard. Network diagrams: Tier 1 Β· Tier 2 Β· Tier 3. Community-requested by Aussie Epic.
oracle-monitor.ps1 Windows PowerShell port v2.5.4-win.1 β€” full logic parity with Linux v2.5.4. PS 5.1 and PS 7 compatible, zero dependencies (native JSON parsing). Includes watch mode (-Watch) and -Config for dual-instance monitoring. Ships UTF-8 with BOM.
config.template.ps1 Windows configuration template for oracle-monitor.ps1.
oracle-monitor-macos.sh macOS port v2.5.4-macos.1 β€” stock bash 3.2 compatible, jq is the only dependency. Includes watch mode (--watch) and --config for dual-instance monitoring.
config-macos.template macOS configuration template for oracle-monitor-macos.sh.
CROSS_PLATFORM_SETUP.md Setup guide for Windows and macOS ports β€” installation, config, Task Scheduler/cron, watch mode, troubleshooting.

Testing

The Windows and macOS ports ship with parallel isolated test harnesses for verifying check_daemon + check_services behavior on your box before scheduling the monitor. Nine scenarios each β€” auto-detect for headless vs Qt, override honored, service check appropriately skipped when Qt is the running daemon, and so on.

Harness Purpose
test-macos-daemon-services.sh Mocks pgrep, launchctl, and $CLI β€” runs 9 scenarios in isolation. Verifies parity with the Linux logic before you point the monitor at a live oracle.
test-win-daemon-services.ps1 Mocks Get-Process, Get-Service, and Invoke-DGBCli β€” runs 9 scenarios under Windows PowerShell 5.1 or 7. Verifies PS-specific behavior including auto-detect candidate loop and Windows Service Qt-skip. Ships UTF-8 with BOM.

Neither harness sends Discord alerts, touches state files, or runs against a real node β€” they're safe to run on any box, even without DigiByte installed.

More tools will be added as the DigiDollar testnet matures toward mainnet activation. Roadmap: See open issues for planned features β€” mainnet migration, bundle signer detection, cross-platform support, and more.


Platform support

The monitor runs natively on all three major platforms. Same 12 checks, same DigiDollar BIP9 pre-activation guard, same quorum state machine, same anti-flap logic, same Qt/headless auto-detect, same Discord card format β€” only the platform plumbing differs.

Platform Script Config template Version
Linux oracle-monitor.sh config.template 2.5.4
Windows 10/11 oracle-monitor.ps1 config.template.ps1 2.5.4-win.1
macOS oracle-monitor-macos.sh config-macos.template 2.5.4-macos.1

Windows needs no dependencies at all (PowerShell parses JSON natively). macOS needs only jq and runs on the stock bash 3.2 every Mac ships with. Setup for both is in CROSS_PLATFORM_SETUP.md. The rest of this README documents the Linux version; the ports behave identically.


oracle-monitor.sh

What it checks (every 5 minutes by default)

  • digibyted daemon process alive (auto-detects headless digibyted or Qt wallet digibyte-qt β€” configurable via DAEMON_PROCESS override)
  • Oracle is running in listoracle
  • Chain sync (blocks vs headers from getblockchaininfo β€” alerts when the node falls more than MAX_CHAIN_BEHIND blocks behind)
  • Peer count (default min: 3)
  • Price freshness (is_stale flag on getoracleprice)
  • Degraded consensus detection (status != ok on getoracleprice)
  • Disk space (default min: 5GB free)
  • Memory usage
  • Swap pressure β€” alerts when swap usage exceeds threshold (default 100 MB). On a properly tuned box with swappiness=10, any meaningful swap usage signals real memory pressure before things get critical (v2.4)
  • digibyted.service and oracle process status via listoracle RPC β€” systemd unit check auto-skips with an INFO line when the Qt wallet is the running daemon (Qt operators typically run outside systemd)
  • Binary version drift detection via RPC (getnetworkinfo β†’ .subversion) β€” works identically for Qt and headless (v2.5)
  • NTP time synchronization
  • Quorum margin tracking β€” counts online oracles via getoracles true using heartbeat_status (stable across MuSig2 round transitions, matches dashboard's "Online Heartbeats" metric), compares against on-chain quorum threshold from getdigidollardeploymentinfo, reports MuSig2 session health. Anti-flap: cooldown timer throttles recovery alerts during volatile periods, hysteresis buffer prevents oscillation at band boundaries

DigiDollar activation status handling

Before DigiDollar BIP9 activates on your target chain, the oracle RPCs (listoracle, getoracleprice, getoracles) return no data β€” the deployment simply isn't live yet. Without special handling, a monitor pointed at a mainnet node right now would fire red alerts every 5 minutes for oracle down, price unknown, and quorum unavailable, even though nothing is actually broken.

The v2.5+ monitors solve this with a pre-flight check. A check_digidollar_active function runs first on every pass, reads getdigidollardeploymentinfo for the current deployment status, and sets a DD_ACTIVE global that the four oracle-dependent checks (check_oracle, check_price, check_services, check_quorum) consult before deciding whether to alert.

When DD_ACTIVE=false, those four checks downgrade "no data" to a blue ℹ️ standby INFO line instead of a red alert β€” showing something like ℹ️ Oracle: standby (DigiDollar deployment: started) in the health summary. The other 8 checks (daemon, chain, peers, disk, memory, swap, service, NTP, version) continue to alert normally on real problems. Result: your Discord channel stays quiet until DigiDollar activates, then automatically switches to full oracle alerting once DD_ACTIVE=true.

This is why a pre-activation mainnet monitor shows an all-green health summary with four ℹ️ standby lines β€” that's correct pre-activation behavior, not a bug. It flips to full oracle data automatically the moment BIP9 locks in.

What it sends

Discord embeds β€” color-coded:

  • πŸ”΄ Red β€” critical (daemon down, oracle stopped, chain stuck, quorum at edge or lost)
  • 🟑 Yellow β€” warnings (low peers, low disk, stale price, degraded consensus, NTP desync, quorum getting thin, swap pressure)
  • 🟒 Green β€” recovery confirmations (quorum healthy, margin improving)
  • πŸ”΅ Blue β€” 12-hour status summary, plus ℹ️ INFO lines for pre-activation standby state
  • Card titles carry the NETWORK_LABEL from your config on every alert β€” health summaries (Testnet26 Health Summary), individual checks (Mainnet β€” πŸ”΄ Node Down), and the --test alert β€” so dual-instance operators can tell which daemon fired an alert at a glance without opening the card (v2.5.3)
  • Footer stamps the monitor version and your oracle identity on every card (e.g. Oracle Monitor v2.5.4 β€” digibyte-maxi (ID 17))

State files in ~/.oracle-monitor/ prevent the same alert firing every 5 minutes β€” you get notified once when something breaks and once again when it recovers. Quorum tracking uses a single quorum_state file that stores the current band and timestamp, with cooldown and hysteresis to prevent alert flapping during network volatility.

All timestamps inside alerts are in UTC for unambiguous reading across timezones. Discord's footer time auto-converts to each viewer's local time.

Discord alert examples

Health summary with quorum tracking and MuSig2 session status:

Oracle Health Summary

Quorum state transition alerts β€” red/yellow/green as oracle count changes:

Quorum Alerts

Both images will be refreshed post-DigiDollar BIP9 mainnet activation β€” see issue #29. The current images still represent the day-to-day healthy-oracle state most operators see; the update after activation will capture the stable long-term post-activation mainnet cards.

Requirements

  • Linux (tested on Ubuntu 24.04 LTS) β€” for Windows and macOS, see Platform support above
  • DigiByte Core v9.26.4 (also compatible with v9.26.2/v9.26.3 and RC44–RC46 β€” uses listoracle, getoracleprice, getdigidollardeploymentinfo, getoracles RPCs)
  • jq (for JSON parsing β€” install with sudo apt install jq)
  • curl
  • A Discord webhook URL β€” create one at: Server Settings β†’ Integrations β†’ Webhooks β†’ New Webhook

Setup

  1. Download the script and config template to your oracle VPS:
   wget https://raw.githubusercontent.com/BaumerCrypto/digidollar-oracle-tools/main/oracle-monitor.sh
   wget https://raw.githubusercontent.com/BaumerCrypto/digidollar-oracle-tools/main/config.template
   chmod +x oracle-monitor.sh
  1. Create your config file from the template:
   mkdir -p ~/.oracle-monitor
   cp config.template ~/.oracle-monitor/config
  1. Edit the config file with your settings:
   nano ~/.oracle-monitor/config

Set your Discord webhook URL, oracle ID, and oracle name. For mainnet, change CLI="digibyte-cli".

  1. Test with --dry-run (runs all checks, prints to terminal, skips Discord):
   ./oracle-monitor.sh --dry-run
  1. Test the webhook:
   ./oracle-monitor.sh --test

You should see a test alert appear in your Discord channel.

  1. Test a full health summary:
   ./oracle-monitor.sh --summary
  1. Add to cron (crontab -e):
   */5 * * * * $HOME/oracle-monitor.sh 2>/dev/null
   0 */12 * * * $HOME/oracle-monitor.sh --summary 2>/dev/null

Flags

Flag What it does
(none) Normal health check β€” alerts only on problems or recovery
--summary Full status summary β€” always sends to Discord
--dry-run Runs all checks, prints to terminal, skips Discord, no state changes
--test Sends a test embed to Discord to verify webhook
--config /path Use alternate config file β€” enables dual-instance monitoring (v2.3+)

Configuration options

All thresholds are configurable in ~/.oracle-monitor/config. The script uses built-in defaults if a value isn't set.

Setting Default Description
DISCORD_WEBHOOK (empty) Discord webhook URL for alerts
ORACLE_ID 0 Your oracle slot ID
ORACLE_NAME my-oracle Your oracle name (shown in Discord embeds)
CLI digibyte-cli -testnet RPC command. Use digibyte-cli for mainnet
WALLET_FLAG -rpcwallet=oracle Wallet flag for RPC calls
MIN_PEERS 3 Minimum peer count before alerting
MIN_DISK_GB 5 Minimum free disk space (GB)
MEM_THRESHOLD 90 Memory usage % above which to alert
SWAP_THRESHOLD_MB 100 Swap usage in MB above which to alert. On a swappiness=10 box, any meaningful swap means real pressure (v2.4)
MAX_CHAIN_BEHIND 10 Blocks behind before alerting
QUORUM_GREEN 12 Oracles reporting at/above this = healthy (no alert). Tuned in v2.5.1 β€” the old 20/12 defaults fired "getting thin" at 2x the 7-of-35 quorum floor. Testnet suggestion: 10
QUORUM_YELLOW 10 Below green but at/above this = "getting thin" warning. Testnet suggestion: 8
QUORUM_COOLDOWN 30 Minutes between quorum recovery alerts. Escalation (worse) always fires immediately. Set to 0 to disable (v2.1+)
QUORUM_HYSTERESIS 3 Recovery buffer β€” must exceed threshold by this many oracles to recover. Prevents flapping at boundaries. Set to 0 to disable (v2.1+)

The quorum minimum (oracle_consensus_required, currently 7) comes from the chain itself via getdigidollardeploymentinfo β€” it's not configurable. Below that threshold, DigiDollar signing halts regardless of your config settings.

Quorum alert bands

Active oracles Status Escalation alert Recovery alert
🟒 12+ Comfortable β€” βœ… Quorum Healthy
🟑 10–11 Getting thin ⚠️ Quorum Getting Thin βœ… Quorum Improved β€” Getting Thin β†’ Healthy
πŸ”΄ 7–9 At quorum edge 🚨 Quorum at Edge βœ… Quorum Improved β€” At Edge β†’ Getting Thin
πŸ’€ Below 7 DD signing halted 🚨 QUORUM LOST βœ… Quorum Recovered β€” LOST β†’ At Edge

Escalation (count drops into a worse band) always fires immediately. Recovery (count rises into a better band) is throttled by QUORUM_COOLDOWN and requires the count to exceed the threshold by QUORUM_HYSTERESIS oracles. This prevents a single oracle bouncing around a boundary from generating a stream of alerts.

Hysteresis recovery thresholds (default QUORUM_HYSTERESIS=3)

Recovery to Threshold Required count
🟒 Healthy QUORUM_GREEN (12) 12 + 3 = 15
🟑 Getting thin QUORUM_YELLOW (10) 10 + 3 = 13
πŸ”΄ At edge oracle_consensus_required (7) 7 + 3 = 10

With QUORUM_HYSTERESIS=0, recovery fires at the exact threshold (v2.0 behavior).

RPC field reference

Both scripts parse specific fields from DigiByte Core RPCs. If a future RC renames a field, these scripts may need updates. Known field names as of RC46:

RPC Field used
listoracle running (not is_running)
listoracle price_usd (not last_price_usd)
getoracleprice price_usd, is_stale, status, oracle_count
getdigidollardeploymentinfo oracle_consensus_required, oracle_total_slots, musig2_session.state, musig2_session.epoch, musig2_session.nonce_count, musig2_session.partial_sig_count
getoracles true last_price_usd, status, heartbeat_status (v2.2: "fresh" = online within 30 min), heartbeat_age_seconds, heartbeat_timestamp, software_version (used by oracle-network-status.sh)
getblockchaininfo chain (used by oracle-network-status.sh v1.4 for network label auto-detection)
getoraclesigners bundle_count, bundles[].height, bundles[].signer_count, bundles[].signer_ids (used by oracle-network-status.sh)

RC45 new RPCs (not used by these scripts yet but available):

RPC Purpose
exportoracleprivkey Export oracle signing key from wallet (wallet-context, usable before activation)
importoracleprivkey Import oracle signing key into wallet (wallet-context, usable before activation)

oracle-network-status.sh

Community-facing Gitter bot that posts oracle network health summaries to the DigiDollar Gitter channel every 12 hours. Unlike oracle-monitor.sh (which watches your own node and alerts you privately via Discord), this script monitors the entire oracle network and reports publicly.

What it reports

  • Network label β€” which chain the report covers (e.g. "Testnet26" or "Mainnet"), auto-detected from getblockchaininfo or set via NETWORK_LABEL in config (v1.4)
  • Fresh Heartbeats β€” active oracle count vs roster size, quorum health status (healthy / thin / critical / lost)
  • Consensus price β€” current DGB/USD price and oracle price feed status
  • MuSig2 session β€” current epoch, signing state, nonce and signature counts
  • BIP9 activation β€” deployment status and signaling bit
  • Last bundle β€” most recent on-chain price bundle block height and signer count
  • Software versions β€” dominant version among active operators (βœ… current vs πŸ”„ outdated during upgrades)
  • Stale oracles (⚠️) β€” were running, went down (liveness concern). Operators are @ mentioned in Gitter for up to 6 cycles (3 days), then suppressed but still listed.
  • Inactive oracles (❌) β€” have key or wallet issues on this testnet. Same @ mention behavior as stale.

Example output

🟒 Oracle Network Status β€” Testnet26 β€” 2026-06-21 23:25 UTC

Fresh Heartbeats: 25/35 (quorum healthy β€” threshold: 7)
Consensus price: $0.002718 (status: active)
MuSig2: epoch 1160, complete, 7/7 nonces, 7/7 sigs
BIP9: active (bit 23)
Last bundle: block 46399, signed by 7 oracles

Software:
  βœ… v9.26.0rc46-g873d6d068... : 21 operators
  βœ… v9.26.0rc46-873d6d068b9f : 2 operators

⚠️ Stale (8):
  β€” ID 5 Ycagel
  β€” ID 11 hallvardo @hallvardo:gitter.im
  β€” ID 13 DigiByteForce @digibyteforce:gitter.im
  β€” ID 22 LivingTheLife
  β€” ID 23 ChozenOne43 @chozenone43:gitter.im
  β€” ID 27 DennisPitallano
  β€” ID 30 DigibyteDaily @dailydgb:gitter.im
  β€” ID 32 3DogsKanab @3dogskanab:gitter.im

❌ Inactive (2):
  β€” ID 31 Peer2Peer
  β€” ID 34 Manu_DGB_oracle

Data sources

RPC What it provides
getblockchaininfo Chain identification β€” auto-detects "test" β†’ Testnet, "main" β†’ Mainnet for header label (v1.4)
getoracles true Per-oracle heartbeat status β€” active, stale, and offline lists
getoracleprice Consensus price, feed status, oracle count
getdigidollardeploymentinfo BIP9 activation, quorum config, MuSig2 session state
getoraclesigners 50 Recent bundle signer participation (50-block window covers at least one full 40-block round)

Requirements

  • Linux (tested on Ubuntu 24.04 LTS)
  • DigiByte Core v9.26.4 (also compatible with v9.26.2/v9.26.3 and RC44–RC46)
  • jq, curl
  • A Matrix bot account joined to #digidollar:gitter.im

Setup

  1. Create a Matrix bot account at Element (e.g. @digidollar-oracle-bot:matrix.org)
  2. Join #digidollar:gitter.im from the bot account
  3. Generate an access token on the VPS:
curl -s -X POST "https://matrix.org/_matrix/client/v3/login" \
  -H "Content-Type: application/json" \
  -d '{"type":"m.login.password","identifier":{"type":"m.id.user","user":"YOUR_BOT_USERNAME"},"password":"YOUR_PASSWORD"}' \
  | jq -r '.access_token'
  1. Get the room ID (Element β†’ Room Settings β†’ Advanced β†’ Internal room ID)
  2. Add to ~/.oracle-monitor/config:
MATRIX_ACCESS_TOKEN="your_token_here"
MATRIX_ROOM_ID="!your_room_id:gitter.im"
  1. Set the network label (optional β€” auto-detected from chain if not set):
NETWORK_LABEL="Testnet26"
  1. For @ mentions (optional): populate the roster mapping file:
wget https://raw.githubusercontent.com/BaumerCrypto/digidollar-oracle-tools/main/oracle-roster.template
cp oracle-roster.template ~/.oracle-monitor/oracle-roster.conf
nano ~/.oracle-monitor/oracle-roster.conf
# Fill in oracle ID to Gitter Matrix ID mappings β€” see template for format
  1. Test: ./oracle-network-status.sh --dry-run
  2. Test: ./oracle-network-status.sh --test
  3. Test mentions: ./oracle-network-status.sh --test-mention
  4. Add to cron: 5 */12 * * * /home/YOUR_USER/oracle-network-status.sh 2>/dev/null

Flags

Flag What it does
(none) Collect data and post to Gitter
--dry-run Collect data, print to terminal, skip Gitter post
--test Send a test message to Gitter to verify Matrix API
--test-mention Send a test @ mention to verify Gitter notifications work
--config /path Use alternate config file β€” enables dual-instance monitoring (v1.4)

Dual-instance monitoring (testnet + mainnet)

When mainnet launches, you can run two independent instances from the same script using --config:

# Testnet (default config)
5 */12 * * * /home/YOUR_USER/oracle-network-status.sh 2>/dev/null
# Mainnet (custom config)
10 */12 * * * /home/YOUR_USER/oracle-network-status.sh --config ~/.oracle-monitor-mainnet/config 2>/dev/null

Each instance uses its own config file and tracks mention state independently. The roster file is shared by default (same 35 operators on both networks). Setup:

mkdir -p ~/.oracle-monitor-mainnet
cp ~/.oracle-monitor/config ~/.oracle-monitor-mainnet/config
# Edit mainnet config: CLI="digibyte-cli", NETWORK_LABEL="Mainnet"
ln -s ~/.oracle-monitor/oracle-roster.conf ~/.oracle-monitor-mainnet/oracle-roster.conf

--config combines with action flags in any order: --config /path --dry-run or --dry-run --config /path.

Important: single-operator bot

This script is designed for a single designated community operator to post to the shared DigiDollar Gitter channel. Running a second instance against the same channel will create duplicate posts. If you want to monitor your own oracle, use oracle-monitor.sh with a Discord webhook to your private channel.


Compatibility

Component Version
OS Linux (Ubuntu 24.04 LTS), Windows 10/11 (PowerShell 5.1+), macOS (bash 3.2+)
DigiByte Core v9.26.4 (also compatible with v9.26.2, v9.26.3, and RC44/RC45/RC46)
Chain testnet26
Oracle protocol v0x03 MuSig2 bundle
oracle-monitor.sh v2.5.4
oracle-monitor.ps1 v2.5.4-win.1
oracle-monitor-macos.sh v2.5.4-macos.1
oracle-network-status.sh v1.5

If you're running a different release and something breaks, please open an issue.


Contributing

Pull requests welcome. If you spot a bug, run into a field-name change on a newer RC, or want to add a check, open an issue or PR.


Author

digibyte-maxi β€” DigiDollar oracle operator (Slot 17)


License

MIT β€” use, fork, modify, share. Credit appreciated but not required.

Disclaimer

These scripts are provided as-is for the DigiByte community. The DigiDollar protocol is live on testnet26; mainnet activation is in progress via miner signaling (BIP9 bit 23, signaling window opened June 1, 2026). Always test on testnet first and back up your oracle wallet.

Releases

No releases published

Packages

 
 
 

Contributors