BoAT Attestor (boat-attest) runs on a VisionFive2 RISC-V board and attests system metrics (memory, CPU usage) to the HashAnchor blockchain attestation platform.
Each attestation creates a tamper-proof, on-chain record of the board's resource usage at a specific point in time.
- VisionFive2 board running Debian Linux (riscv64)
- Python 3.11 with venv
- Network connectivity to HashAnchor (
hashanchor.xid.network) - A HashAnchor tenant account with API key
mkdir -p ~/boatattestor
python3 -m venv ~/boatattestor/venv
~/boatattestor/venv/bin/pip install requests "eth_account<0.11" "pydantic<2" ed25519Copy boat-attest.py and boat-attest (launcher script) to ~/boatattestor/.
chmod +x ~/boatattestor/boat-attest ~/boatattestor/boat-attest.pyThe device must be registered with your HashAnchor tenant before it can submit attestations.
Step 1: Pre-register (from any machine with your API key)
curl -X POST https://hashanchor.xid.network/v1/device/register \
-H "Authorization: Bearer ha_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"deviceId": "BoatAttestor-VF2-YOUR_MAC"}'The device ID is derived from eth0's MAC address with colons removed. Find it with:
cat /sys/class/net/eth0/address
# Example: 6c:cf:39:00:b0:8c → BoatAttestor-VF2-6ccf3900b08cStep 2: Run boat-attest once (on the board)
The first run generates an Ed25519 keypair. Then register the public key:
~/boatattestor/boat-attest --dry-run
# Note the "Device key loaded/created: <public_key_hex>"Step 3: Activate with public key
curl -X POST https://hashanchor.xid.network/v1/device/register \
-H "Authorization: Bearer ha_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"deviceId": "BoatAttestor-VF2-YOUR_MAC", "publicKey": "PUBLIC_KEY_HEX", "algorithm": "ed25519"}'You should see {"status":"activated",...}.
~/boatattestor/boat-attest --api-key ha_YOUR_API_KEYOr set the environment variable:
export HASHANCHOR_API_KEY=ha_YOUR_API_KEY
~/boatattestor/boat-attestRequires a funded wallet with USDC deposited into the Circle Gateway on Arc Testnet.
One-time wallet setup:
- The first run without
--api-keycreates a wallet at~/.boat-attest-wallet.json - Fund the wallet with USDC on Arc Testnet (chain ID 5042002, faucet: https://faucet.circle.com)
- Deposit USDC into the Gateway contract using
gateway-deposit.py:
~/boatattestor/venv/bin/python3 ~/boatattestor/gateway-deposit.py 50000Then run without --api-key:
~/boatattestor/boat-attestPreview what would be attested without submitting:
~/boatattestor/boat-attest --dry-runEnable verbose output:
BOAT_DEBUG=1 ~/boatattestor/boat-attest --api-key ha_YOUR_API_KEYEach attestation captures a JSON snapshot:
{
"timestamp": 1773475236,
"memory": { "total_kb": 8079824, "available_kb": 6967860, "used_kb": 1111964 },
"cpu": { "user": 299902, "system": 309210, "idle": 22432569, ... },
"loadavg": { "1min": 0.8, "5min": 0.55, "15min": 0.39 }
}The JSON is SHA-256 hashed, signed with the device's Ed25519 key, and submitted to HashAnchor. The timestamp ensures each submission produces a unique hash.
After a successful attestation, verify the hash on-chain:
https://hashanchor.xid.network/v1/verify/0xYOUR_HASH
| File | Location | Purpose |
|---|---|---|
boat-attest |
~/boatattestor/ |
Launcher script |
boat-attest.py |
~/boatattestor/ |
Main program |
gateway-deposit.py |
~/boatattestor/ |
USDC Gateway deposit helper |
venv/ |
~/boatattestor/ |
Python virtual environment |
.boat-attest-device.json |
~/ |
Ed25519 device keypair |
.boat-attest-wallet.json |
~/ |
Secp256k1 wallet (x402 mode) |
To attest every hour via cron:
crontab -e
# Add:
0 * * * * ~/boatattestor/boat-attest --api-key ha_YOUR_API_KEY >> ~/boatattestor/attest.log 2>&1