12 KiB
AGENTS.md — entry point for AI agents and security researchers
This document is the canonical entry point for any AI agent or human researcher who wants to deploy a Montana node, stress-test it, audit the code, and report findings. Read top-to-bottom; commands are copy-paste ready.
What Montana is, in 60 seconds
Montana is a from-scratch post-quantum blockchain. Three architectural primitives:
- Sequential-delay TimeChain — globally-ordered windows of ~60 seconds each, sealed by a sequential SHA-256 chain (D = 325 000 000 iterations per window). Cannot be parallelized, cannot be skipped. Verification costs the same order of work as computation, so this is not a VDF in the efficient-verification literature sense.
- Time-as-scarcity — anti-spam through window-rate-limits, chain_length thresholds, seniority gating. No transaction fees. No gas. Cannot accelerate operations by paying.
- Post-quantum where the protocol currently claims it — ML-DSA-65 (FIPS 204) for consensus signatures, ML-KEM-768 (FIPS 203) at the application layer, SHA-256 for hashing and TimeChain, PBKDF2 for key derivation. Transport confidentiality is tracked separately through the Noise_PQ migration.
Spec is the single source of truth: ../Montana Protocol v35.25.1.md. ~600 KB markdown, full protocol specification.
Status
Pre-mainnet v0.2. No mainnet date. No token launch. No premine. The implementation is M1-M6 + M9 ready for external audit; M8 (node binary) is still in progress, with known deviations and closures tracked in docs/SPEC_DEVIATIONS.md. DEV-012 (multi-node proposal apply in the node binary) remains the current mainnet blocker.
Singleton means: each deployed node is its own genesis bootstrap, ticking TimeChain locally and writing its own state. Until multi-node proposal apply is wired into the binary, nodes do not provide production BFT consensus.
This is intentional for v0.2 — it lets you deploy and break a Montana node end-to-end without needing a production network of peers.
Deploy
One command on a clean Linux VPS (Ubuntu 24.04 / Debian 12 / Fedora / Alpine)
git clone https://github.com/efir369999/Montana.git /opt/montana && \
sudo bash /opt/montana/Code/scripts/install-vps-full.sh
What this does (≈10 minutes on a 1 vCPU VPS):
- Installs system deps (build-essential, clang, git, perl, ca-certificates)
- Installs Rust toolchain (rustup, stable channel)
- Builds
montana-nodefrom source (cargo build --release -p montana-node) - Creates system user
montanaand/var/lib/montana - Generates 24-word recovery mnemonic and prints it once — save it immediately, no second chance
- Installs systemd unit with hardening (
User=montana,NoNewPrivileges,ProtectSystem=strict) - Starts
montana-node.service - Installs xray Reality VPN endpoint as a separate systemd service (optional, runs alongside the node — see
montana-vpn/README.md)
After install:
systemctl status montana-node # is it running
journalctl -u montana-node -f # live logs (one line per ~60s window)
montana-node status --data-dir /var/lib/montana # phase, balance, current_window
Just the node, no VPN
sudo bash /opt/montana/Code/scripts/install-vps.sh
Just the VPN, no node
sudo bash /opt/montana/Code/montana-vpn/install.sh
macOS (Apple Silicon)
git clone https://github.com/efir369999/Montana.git ~/Montana && \
bash ~/Montana/Code/scripts/install-local-mac.sh
This installs the node under ~/Library/Application Support/Montana/node/ with a launchd agent.
Build from source manually
See docs/build-from-source.md for the reproducible-build path. Short version:
cd Code
cargo build --release -p montana-node
./target/release/montana-node --help
Verify the node is healthy
After 5 minutes of running:
montana-node status --data-dir /var/lib/montana
Expected output (numbers will differ):
phase : Active
current_window : 5
D (current) : 325000000
NodeTable : 1 records
balance : 65000000000 nɈ (5 windows × 13 Ɉ baseline emission)
supply (closed-form) : 78000000000 nɈ (must equal Σ balance + future emission curve)
Healthy invariants:
phase == Active(genesis bootstrap activates immediately, no Candidate VDF wait)current_windowincreases by exactly 1 per ~60 secondsΣ balance == supply (closed-form) × correction-for-emission-schedulestate_rootafter each apply_proposal byte-equals the expected recompute (logged at INFO level)
Pathological signs (file an Issue):
- Phase regresses (Active → Bootstrap)
current_windowstops advancing for >2 minutesstate_rootmismatch in logs- Process panics or OOMs
- Disk usage grows >10 MiB per hour (it should be ~50 KiB per hour)
Stress test — what to throw at it
We have not stress-tested at scale. Here is what would help:
1. VDF correctness under chaos
Kill the node mid-window and restart. State must resume from the last cemented window without divergence. Repeat 100×, automate with kill -9 + immediate systemctl start.
for i in {1..100}; do
systemctl restart montana-node
sleep $((RANDOM % 30 + 5))
systemctl kill -s KILL montana-node
done
journalctl -u montana-node --since "10 minutes ago" | grep -iE 'panic|error|state_root mismatch'
Expected: zero panic, zero state_root mismatch. Any divergence = blocker-level finding.
2. Disk-full handling
Fill /var/lib/montana to 100% mid-operation. Node must fail gracefully, not corrupt state.
fallocate -l $(df --output=avail /var/lib/montana | tail -1)k /var/lib/montana/_filler
journalctl -u montana-node -f
# clean up:
rm /var/lib/montana/_filler
3. Clock skew
Set system clock backwards 1 hour mid-operation. Node uses VDF iterations as the clock, not wall-time, so it should ignore the jump.
date -s "$(date -d '1 hour ago')"
sleep 120
date -s "$(date)" # let NTP correct it back
journalctl -u montana-node --since "5 minutes ago"
Expected: no behavior change. Wall-time is not consensus-critical.
4. Determinism — two nodes, same mnemonic, same state_root
Critical. If two independent installs of the same git rev with the same seed mnemonic produce different state_root after N windows — that is a consensus-fork bug.
# on host A:
montana-node init --data-dir /tmp/a --mnemonic "<same 24 words>"
montana-node start --data-dir /tmp/a --max-windows 100 --d-test-override 1000
# on host B:
montana-node init --data-dir /tmp/b --mnemonic "<same 24 words>"
montana-node start --data-dir /tmp/b --max-windows 100 --d-test-override 1000
# compare:
diff <(sha256sum /tmp/a/proposals/*.bin) <(sha256sum /tmp/b/proposals/*.bin)
Expected: identical SHA-256 sums for every proposal. Any diff = consensus-fork-level finding.
5. Memory / CPU profiling
Run the node for 24 hours. Monitor RSS over time.
while true; do
ps -p $(pgrep montana-node) -o rss=,vsz= >> /tmp/montana-mem.log
sleep 60
done
Expected: RSS ≈ stable around 30-50 MiB (peak ~100 MiB during VDF burst). Continuous growth >1 MiB/hour = leak.
6. Fuzz inputs to apply_proposal
The state machine apply_proposal(state, proposal) → state' must reject malformed input deterministically. Use cargo-fuzz:
cd Code
cargo install cargo-fuzz
cargo fuzz run apply_proposal_arbitrary -- -max_total_time=3600
(Fuzz harness scaffolding may not yet exist for every entry point — adding more = welcome PR.)
Audit the code against the spec
The spec is at ../Montana Protocol v35.25.1.md, authoritative.
Known deviations
docs/SPEC_DEVIATIONS.md lists known deviations, acknowledgments, and closures across the implementation. Each entry:
- Spec quote
- Code location
- What the code actually does
- Severity (mainnet blocker / medium / cosmetic)
- Closure path
Any un-documented deviation you find = high-value finding. File as an Issue with:
- Spec section + dossier line number
- Code path (
crates/<crate>/src/<file>:LLL) - Test that demonstrates the deviation
- Suggested fix or "needs architect input"
Internal audit infrastructure
AUDIT.md— pre-audit self-attestation, single-page summary for an external audit firmdocs/audit-checklist.md— what we covered internallydocs/security-cards.md— per-primitive security analysis (FN-DSA, ML-KEM, SHA-256 VDF, PBKDF2)
Spec-vs-code comments
Every consensus-critical decision in the code references the spec section it implements:
// spec, раздел "Consensus encoding layer"
fn encode(...) { ... }
Grep for // spec, раздел to find all anchored references:
rg "// spec, раздел" --type rust
Report findings
GitHub Issues + Pull Requests at https://github.com/efir369999/Montana
Issue template (free-form, no enforcement):
Title: [SEVERITY] short description
Severity: blocker / high / medium / low / informational
What you did:
- command sequence to reproduce
What you expected:
- per spec section X.Y, expected behavior is Z
What happened instead:
- actual output / log excerpt / state diff
Spec reference:
- Protokol/Montana Protocol v35.25.1.md, section "X.Y"
Suggested fix (if any):
- <or "needs architect input">
PR template:
- Reference the Issue this PR closes
- Include test that fails before the fix and passes after
- Update
docs/SPEC_DEVIATIONS.mdif closing a known deviation - Run
cargo fmt + clippy + test --all + build --release(all must be green)
No NDA. No engagement contract. Public review by default.
Things that would be especially welcome
- Fuzz harness for every public entry point (currently partial)
- Property-based test coverage for
apply_*functions (currently has unit + invariants, not property-based) - Differential testing harness comparing this Rust impl vs an independent re-implementation (Go / Python / Zig)
- CI matrix across Linux x86_64 + ARM64 + macOS ARM64 + Windows (currently single-platform local)
- Benchmark suite measuring VDF iter/sec across CPU classes (we have one micro-bench, not a suite)
- Deterministic-replay framework (record all inputs to apply_proposal, replay byte-for-byte)
- Side-channel analysis on PBKDF2 / signature verify (timing, cache, branching)
- Audit of the crowdsec / fail2ban / ufw default rules for the VPS installer
- Independent translation of the spec (currently RU primary, EN fragments)
What we will NOT do
- We will not sell tokens. Not now, not at mainnet. Montana has no premine, no presale, no airdrop schedule. Block reward (13 Ɉ per window to operator) is the only emission, paid to whoever ran the VDF for that window.
- We will not add fees. Anti-spam is time-based by architectural invariant
[I-15]of the spec. - We will not add ECDSA / RSA / curve25519 fallback. Post-quantum from day one is invariant
[I-1]. - We will not add KYC, allowlist, or compliance backdoors. Privacy-by-default is invariant
[privacy-default].
Contact
- GitHub Issues: https://github.com/efir369999/Montana/issues
- Mastodon (announcements only, no support): see
montana-vpn/MASTODON_ANNOUNCEMENT.md - No email, no Discord, no Telegram — public on-record review only
Pre-mainnet. Break it, fix it, send PRs.