Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
39d9865
test(cli): repair reproducible TCP bridge harness
epicexcelsior May 31, 2026
effe727
fix(wallet): validate execute-payment addresses
epicexcelsior May 31, 2026
7dff488
feat(cli): add headless node preflight launcher
epicexcelsior May 31, 2026
9a0c266
docs(cli): mark desktop BLE path experimental
epicexcelsior May 31, 2026
5328864
fix(cli): harden headless preflight lifecycle
epicexcelsior May 31, 2026
ad87b4b
docs(cli): fix contributor setup URLs
epicexcelsior May 31, 2026
b2d96bd
fix(cli): remove unreachable default hub
epicexcelsior May 31, 2026
98dde91
fix(cli): make RNode setup noninteractive
epicexcelsior May 31, 2026
b729066
fix(cli): reject unknown setup flags
epicexcelsior May 31, 2026
fc8e6b2
fix(wallet): protect generated keypair files
epicexcelsior May 31, 2026
e7f9c6f
fix(wallet): restrict legacy keypair permissions
epicexcelsior May 31, 2026
4e883ce
fix(cli): reject incompatible setup modifiers
epicexcelsior May 31, 2026
048d8b9
fix(cli): clear failed headless startup pid
epicexcelsior May 31, 2026
c8cc785
fix(cli): reject non-object gateway requests
epicexcelsior May 31, 2026
c986193
fix(wallet): handle malformed signing inputs
epicexcelsior May 31, 2026
7ac7ab0
fix(beacon): validate cosign request params
epicexcelsior May 31, 2026
6432b33
fix(wallet): validate Arcium boundary payloads
epicexcelsior May 31, 2026
b7cb783
fix(cli): keep RPC credentials out of logs and args
epicexcelsior May 31, 2026
292095a
fix(cli): redact manual Arcium helper errors
epicexcelsior May 31, 2026
04da2c9
chore(deps): apply non-breaking npm audit updates
epicexcelsior May 31, 2026
ef9cba9
fix(wallet): repair discovered nonce key permissions
epicexcelsior May 31, 2026
ca750ae
fix(mesh): reject non-object RPC responses
epicexcelsior May 31, 2026
5f7d921
fix(cli): handle scalar RPC error payloads
epicexcelsior May 31, 2026
41a291b
fix(cli): reject malformed RPC result payloads
epicexcelsior May 31, 2026
d8d30a1
fix(cli): prevent confidential balance downgrade
epicexcelsior May 31, 2026
6f38c43
fix(mesh): validate beacon hash characters
epicexcelsior May 31, 2026
61bbd54
fix(cli): harden interactive broadcast retry
epicexcelsior May 31, 2026
4a3f7ad
fix(wallet): validate nonce creation RPC results
epicexcelsior May 31, 2026
df8c8a6
fix(wallet): validate unsigned transaction amounts
epicexcelsior May 31, 2026
5d6dd3c
fix(cli): validate interactive numeric inputs
epicexcelsior May 31, 2026
c66bb21
fix(cli): decline relay prompt on EOF
epicexcelsior May 31, 2026
bf9b50a
fix(cli): require positive request timeout
epicexcelsior May 31, 2026
40464ef
fix(mesh): cap expanded response payloads
epicexcelsior May 31, 2026
8da4887
fix(mesh): restrict persisted identity permissions
epicexcelsior May 31, 2026
18f47fc
fix(setup): create Reticulum identities privately
epicexcelsior May 31, 2026
7e5e364
fix(cli): validate announce intervals
epicexcelsior May 31, 2026
8933a86
fix(cli): restrict local credential files
epicexcelsior May 31, 2026
aa32c9c
fix(arcium): restrict helper credential files
epicexcelsior May 31, 2026
3dac2d2
fix(cli): restrict headless launcher state files
epicexcelsior May 31, 2026
2747487
fix(mesh): bound gateway relay payloads
epicexcelsior May 31, 2026
6937126
fix(mesh): reject oversized raw responses
epicexcelsior May 31, 2026
a7786cc
fix(beacon): restrict cosign transaction shape
epicexcelsior May 31, 2026
78e71c9
fix(wallet): repair signing key permissions
epicexcelsior May 31, 2026
777222c
fix(demo): protect durable nonce key files
epicexcelsior May 31, 2026
993107d
fix(cli): validate interactive RPC responses
epicexcelsior May 31, 2026
36b1308
fix(cli): parse payment amounts exactly
epicexcelsior May 31, 2026
c2b7c8b
fix(setup): validate nonce bootstrap RPC replies
epicexcelsior May 31, 2026
42fdecc
fix(demo): validate mesh RPC responses
epicexcelsior May 31, 2026
9575b93
fix(setup): recover from wallet bootstrap failures
epicexcelsior May 31, 2026
0703c3e
fix(arcium): validate shim and env boundaries
epicexcelsior May 31, 2026
383178b
fix(arcium): keep encrypt plaintext out of argv
epicexcelsior May 31, 2026
9b834cd
fix(cli): disable unsupported confidential balance
epicexcelsior May 31, 2026
81542a1
fix(wallet): validate Arcium instruction fields
epicexcelsior May 31, 2026
320e91e
fix(mesh): reject malformed compressed responses
epicexcelsior May 31, 2026
68372c3
fix(arcium): repair whitelist helper invocation
epicexcelsior May 31, 2026
c4366f8
fix(arcium): reject inconsistent shim exits
epicexcelsior May 31, 2026
07e7a40
fix(cli): reject out-of-range RPC counters
epicexcelsior May 31, 2026
e568f9c
fix(cli): escape untrusted terminal output
epicexcelsior May 31, 2026
2848d76
fix(gateway): reject malformed upstream responses
epicexcelsior May 31, 2026
ac4fa35
fix(beacon): require canonical cosign inputs
epicexcelsior May 31, 2026
6f30751
fix(arcium): validate rescue payload widths
epicexcelsior May 31, 2026
7092282
fix(cli): sanitize demo and preflight output
epicexcelsior May 31, 2026
7012b82
fix(cli): skip malformed dotenv entries
epicexcelsior May 31, 2026
91d75fb
fix(cli): require URL for custom networks
epicexcelsior May 31, 2026
da4447c
fix(cli): bound rendered simulation logs
epicexcelsior May 31, 2026
692713b
fix(cli): bound rendered response details
epicexcelsior May 31, 2026
efa9cc8
fix(mesh): ignore stale link close callbacks
epicexcelsior May 31, 2026
1776faa
fix(arcium): validate helper inputs at boundary
epicexcelsior May 31, 2026
d4317e8
fix(rpc): preserve empty error responses
epicexcelsior May 31, 2026
ca3970c
fix(cli): refuse symlinked private state writes
epicexcelsior May 31, 2026
f6af957
fix(mesh): cancel superseded link attempts
epicexcelsior May 31, 2026
66358d4
fix(wallet): handle nonce key write failures
epicexcelsior May 31, 2026
ac7e1c6
fix(cli): escape rendered local wallet paths
epicexcelsior May 31, 2026
e67dba5
fix(wallet): reject unsafe keypair file types
epicexcelsior May 31, 2026
a909a18
fix(headless): reject unsafe state file types
epicexcelsior May 31, 2026
09d2138
fix(state): guard private file reads
epicexcelsior May 31, 2026
69e4de8
fix(demo): handle supplied keypair load failures
epicexcelsior May 31, 2026
5823a32
fix(setup): preserve launcher option values
epicexcelsior May 31, 2026
6f83a72
fix(gateway): stream bounded rpc responses
epicexcelsior May 31, 2026
f8c2941
fix(preflight): bound rpc health response
epicexcelsior May 31, 2026
f8308de
fix(setup): preserve nonce key after uncertain submit
epicexcelsior May 31, 2026
af6a049
fix(setup): bound nonce bootstrap rpc responses
epicexcelsior May 31, 2026
6aa8e8c
fix(wallet): atomically persist keypairs
epicexcelsior May 31, 2026
4b37d5d
fix(setup): atomically persist generated keypairs
epicexcelsior May 31, 2026
bfa6b1f
fix(mesh): refresh known beacon identities on announce
epicexcelsior May 31, 2026
8af56ea
fix(beacon): honor configured ca bundle
epicexcelsior May 31, 2026
6854c14
fix(wallet): bound local keypair discovery
epicexcelsior May 31, 2026
ba4cfbf
fix(arcium): validate shim payment signature
epicexcelsior May 31, 2026
44a7f71
fix(arcium): clean up failed client init
epicexcelsior May 31, 2026
b279886
fix(mesh): preserve first raced rpc response
epicexcelsior May 31, 2026
5b0681f
fix(setup): atomically write generated config files
epicexcelsior May 31, 2026
71383e5
fix(wallet): clean unused generated nonce keys
epicexcelsior May 31, 2026
9f30c20
fix(client): wait for discovery after known beacon failure
epicexcelsior May 31, 2026
eaecdf3
fix(mesh): secure delayed transport identity
epicexcelsior May 31, 2026
2b31141
fix(setup): preserve quoted filesystem paths
epicexcelsior May 31, 2026
ccab694
test(cli): quote tcp harness checkout paths
epicexcelsior May 31, 2026
b7249e7
fix(beacon): validate queued Arcium account metadata
epicexcelsior May 31, 2026
a7f09b3
fix(arcium): reject malformed payment metadata locally
epicexcelsior May 31, 2026
a2248f2
fix(arcium): validate client configuration locally
epicexcelsior May 31, 2026
43b9814
fix(setup): escape generated systemd service paths
epicexcelsior May 31, 2026
dfe0ae2
fix(setup): reject unsafe RNode serial values
epicexcelsior May 31, 2026
fb2471c
fix(setup): validate selected RNode serial value
epicexcelsior May 31, 2026
f71bce2
fix(setup): reject unsafe RNode env before logging
epicexcelsior May 31, 2026
a53f150
fix(arcium): guard node helper credential reads
epicexcelsior May 31, 2026
900695c
fix(arcium): bound node helper credential reads
epicexcelsior May 31, 2026
f6cf43e
fix(arcium): bound initializer simulation logs
epicexcelsior May 31, 2026
145b838
ci(cli): run reliability suite on pushes
epicexcelsior May 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/cli-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: CLI tests

on:
pull_request:
push:

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- uses: actions/setup-node@v4
with:
node-version: "20"
- name: Run test suite
run: ./scripts/test.sh -q
- name: Run static checks
run: |
.venv-test/bin/python -m pip check
python3 -m py_compile \
client.py shared.py rpc.py menu.py wallet.py mesh.py beacon.py \
arcium_client.py scripts/preflight.py scripts/exit_node.py \
scripts/demo_durable_nonce_relay.py tests/test_tcp_bridge.py
bash -n setup.sh scripts/headless-node.sh scripts/test.sh
for file in rescue_shim.mjs scripts/*.mjs; do
node --check "$file"
done
8 changes: 5 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
venv/
.venv/
.venv-test/
config/storage/
__pycache__/
node_modules/
Expand All @@ -10,6 +11,7 @@ run_client.sh
wallet.json
wallet_*.json
nonce_*.json
config/*/storage/
config/*/interfaces/
*.identity
config/**/storage/
config/**/interfaces/
config/**/anonmesh_exit_identity
*.identity
105 changes: 81 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

**Mesh First, Chain When It Matters.**

anonmesh is a Python MVP for tunneling Solana JSON-RPC requests over [Reticulum's](https://reticulum.network/) end-to-end encrypted mesh network. Off-grid devices interact with the Solana blockchain through connected gateway nodes ("Beacons") over virtually any transport medium — LoRa, BLE, WiFi, Packet Radio, TCP hubs, and more.
anonmesh is a Python MVP for tunneling Solana JSON-RPC requests over [Reticulum's](https://reticulum.network/) end-to-end encrypted mesh network. Off-grid devices interact with the Solana blockchain through connected gateway nodes ("Beacons") over supported Reticulum transports such as LoRa, WiFi, Packet Radio, and TCP hubs. Desktop BLE relay remains experimental.

After relaying a transaction, the Beacon co-signs and submits an `execute_payment` instruction to the **ble_revshare** Anchor program, logging encrypted payment statistics via [Arcium MPC](https://arcium.com/) — so revenue-share accounting happens on-chain without leaking raw amounts.
When configured, a Beacon can co-sign and submit an `execute_payment` instruction to the **ble_revshare** Anchor program after relaying a transaction with the required Arcium metadata. This logs encrypted payment statistics via [Arcium MPC](https://arcium.com/) without leaking raw amounts.

## Architecture

Expand All @@ -30,7 +30,7 @@ After relaying a transaction, the Beacon co-signs and submits an `execute_paymen
## Quickstart

```bash
git clone https://github.com/Magicred-1/anonmesh_cli.git
git clone https://github.com/anonmesh/anonmesh_cli.git
cd anonmesh_cli
npm install
chmod +x setup.sh
Expand All @@ -45,34 +45,43 @@ chmod +x setup.sh
./setup.sh --beacon # beacon only
./setup.sh --client # client only (adds solders, qrcode)
./setup.sh --both # both
./setup.sh --systemd # also install beacon as a systemd service
./setup.sh --ble # add Bluetooth Low Energy transport
./setup.sh --meshtastic # add Meshtastic / LoRa transport
./setup.sh --wallet-setup # generate signing keypair + durable nonce account
./setup.sh --mainnet # target Solana mainnet-beta instead of devnet
./setup.sh --beacon --systemd # also install a beacon systemd service
./setup.sh --beacon --ble # install experimental BLE research deps
./setup.sh --beacon --meshtastic # install Meshtastic research deps
./setup.sh --beacon --rnode # configure detected RNode LoRa hardware
./setup.sh --client --wallet-setup # interactively create wallet + nonce state
./setup.sh --beacon --mainnet # target Solana mainnet-beta instead of devnet
```

For unattended RNode setup, specify the serial device and legal radio region
explicitly:

```bash
ANONMESH_RNODE_PORT=/dev/ttyUSB0 ANONMESH_RNODE_REGION=us \
./setup.sh --beacon --rnode
```

## Configuration

Copy `.env.example` to `.env` and edit:
Create `.env` only if you need optional Arcium or wallet overrides:

```bash
cp .env.example .env
install -m 600 /dev/null .env
```

Key variables:

| Variable | Default | Description |
|---|---|---|
| `SOLANA_NETWORK` | `devnet` | `devnet` or `mainnet` |
| `ARCIUM_ENABLED` | `1` | Set to `0` to disable Arcium MPC |
| `ARCIUM_PAYER_KEYPAIR` | `~/.config/solana/id.json` | Keypair that pays Arcium computation fees |
| `SOLANA_NETWORK` | `devnet` | Launcher network: `devnet` or `mainnet` |
| `SOLANA_RPC_URL` | public network endpoint | Optional beacon RPC override |
| `ARCIUM_ENABLED` | `0` | Set to `1` to enable Arcium MPC |
| `ARCIUM_PAYER_KEYPAIR` | *(unset)* | Keypair that pays Arcium computation fees |
| `ARCIUM_RPC_URL` | devnet public endpoint | RPC for Arcium transactions |
| `ARCIUM_MXE_PUBKEY_HEX` | *(pre-filled for devnet)* | MXE x25519 public key |
| `ARCIUM_MXE_PUBKEY_HEX` | *(unset)* | MXE x25519 public key |
| `ARCIUM_CLUSTER_OFFSET` | `456` | `456` = devnet, `2026` = mainnet-alpha |
| `ARCIUM_BROADCASTER_TOKEN_ACCOUNT` | *(derived)* | Beacon's SPL token account for rev-share |
| `ARCIUM_TREASURY_TOKEN_ACCOUNT` | *(derived from broadcaster)* | Treasury token account |
| `ANNOUNCE_INTERVAL` | `300` | Seconds between Reticulum re-announces |

## Usage

Expand All @@ -97,11 +106,42 @@ The beacon prints its **DESTINATION HASH** on startup — share this with client
./run_client.sh <BEACON_HASH> --balance <SOLANA_ADDRESS>
```

### 3. Run a Headless Exit Node

Use the headless launcher for a laptop or Linux server that only forwards RPC:

```bash
./scripts/headless-node.sh preflight
./scripts/headless-node.sh start
./scripts/headless-node.sh status
./scripts/headless-node.sh logs
./scripts/headless-node.sh stop
```

Override `ANONMESH_CONFIG_DIR`, `ANONMESH_NETWORK`, or `ANONMESH_RPC_URL` when the defaults do not match your deployment.
Use the RPC URL environment variables for credential-bearing endpoints. The
launchers keep those URLs out of process arguments, and runtime logs redact
credentials, path tokens, and query parameters.

## Testing

```bash
# Fresh local test environment + unit tests
npm test -- -q

# Localhost Reticulum relay → headless exit node → Solana devnet
.venv-test/bin/python tests/test_tcp_bridge.py
```

## Arcium MPC — execute_payment flow

The current Arcium integration records encrypted payment statistics only.
Confidential SOL balance queries are not implemented. The retained client
`--cbalance` compatibility flag fails closed without relaying an address.

After the beacon relays a `sendTransaction` containing Arcium metadata, it:

1. Calls `rescue_shim.mjs get_arcium_accounts` to derive all on-chain PDA addresses.
1. Calls `rescue_shim.mjs arcium_accounts` to derive all on-chain PDA addresses.
2. Encrypts the payment amount with x25519 + RescueCipher (shim-side).
3. Auto-creates any missing SPL token ATAs (payer, recipient, treasury, broadcaster).
4. Builds a durable-nonce transaction with `execute_payment` on the **ble_revshare** program (`7xeQNUggKc2e5q6AQxsFBLBkXGg2p54kSx11zVainMks`).
Expand Down Expand Up @@ -130,7 +170,7 @@ node scripts/init_comp_def_once.mjs
|---|---|
| `check_arcium_accounts.mjs` | Verify all Arcium PDAs / ATAs exist on devnet |
| `fetch_idl.mjs` | Fetch the deployed program IDL |
| `get_whitelists.js` | List whitelisted mints |
| `get_whitelists.mjs` | List whitelisted mints |
| `init_comp_def_once.mjs` | Initialise the `payment_stats` computation definition |

Run any with:
Expand All @@ -141,20 +181,28 @@ node scripts/<script>.mjs [args]

## Reticulum configuration

`setup.sh` writes `~/.reticulum/config` automatically. A working example (with the reliable public hubs) is included as [`reticulum_config`](reticulum_config) in this repo — copy it over if you need to reset:
`setup.sh` writes `~/.reticulum/config` automatically. Re-run setup to reset that config. The included [`reticulum_config`](reticulum_config) file is an RNode reference sample; edit its serial port before using it:

```bash
cp reticulum_config ~/.reticulum/config
# Edit the RNode LoRa port for this machine.
```

`setup.sh` restricts `~/.reticulum` and generated launchers use `umask 077`.
When starting `rnsd` directly, set the same umask before its first run so its
persisted transport identity is owner-only:

```bash
umask 077
rnsd
```

Public TCP hubs configured by default:

- `dublin.connect.reticulum.network:4965` (RNS Testnet Dublin)
- `reticulum.betweentheborders.com:4242`
- `rns.beleth.net:4242`
- `dfw.us.g00n.cloud:6969`

BLE and Meshtastic / LoRa interfaces are also configured (disabled by default; enable via setup flags).
RNode LoRa is optional. `setup.sh --ble` installs `bleak` for research only; it does not configure a supported desktop BLE relay. `setup.sh --meshtastic` installs the Python dependency but requires a separately supplied Reticulum interface module. Phone BLE uses the separate Android/iOS native client.

## Dependencies

Expand All @@ -166,8 +214,8 @@ BLE and Meshtastic / LoRa interfaces are also configured (disabled by default; e
| `lxmf` | Beacon discovery over the mesh |
| `requests` | Solana RPC calls |
| `solders` | Offline transaction signing (client) |
| `bleak` | BLE transport (optional) |
| `meshtastic` | LoRa transport (optional) |
| `bleak` | Experimental desktop BLE research dependency |
| `meshtastic` | Experimental Meshtastic research dependency |
| `qrcode` | Wallet QR display (optional) |

### Node.js (managed by `npm install`)
Expand All @@ -183,7 +231,12 @@ BLE and Meshtastic / LoRa interfaces are also configured (disabled by default; e

Transactions sent over the mesh can be delayed by minutes or hours. A [durable nonce account](https://docs.solana.com/developing/programming-model/transactions#durable-transaction-nonces) replaces the expiring blockhash so the signed transaction stays valid until it lands on-chain.

`setup.sh --wallet-setup` generates a signing keypair and creates a nonce account on your behalf (~0.00145 SOL rent-exempt deposit, recoverable).
`setup.sh --wallet-setup` is intentionally interactive. It generates a signing
keypair and can create a nonce account on your behalf after confirmation
(~0.00145 SOL rent-exempt deposit, recoverable). Review the prompts before using
it with a funded wallet. Generated and reused wallet keypair JSON files, plus
generated nonce keypair files, are restricted to owner-only `0600` permissions.
Private key reads and writes reject final symlinks and non-regular files.

The client partially signs the transaction (payer slot); the beacon co-signs (broadcaster slot) before submitting to Solana.

Expand All @@ -196,3 +249,7 @@ sudo systemctl start anonmesh-beacon
sudo systemctl status anonmesh-beacon
journalctl -u anonmesh-beacon -f
```

`--systemd` requires `sudo`, writes `/etc/systemd/system/anon0mesh-beacon.service`,
and enables the service for boot. Run it only when persistent beacon operation is
intended.
Loading