Balise Bitcoin via Meshtastic : diffuser l’état de la chaîne hors réseau
Réponse rapide
Une balise Bitcoin est un nœud auto-hébergé qui diffuse périodiquement les signes vitaux de la chaîne — hauteur de bloc, hash du sommet et un instantané des frais — sous forme de simple message texte Meshtastic par radio LoRa. Trois appels bitcoin-cli (getblockcount, getbestblockhash, estimatesmartfee) alimentent une diffusion meshtastic --sendtext sur un horaire. Quiconque est sur le canal du mesh reste informé du réseau Bitcoin sans internet, sans opérateur et sans compte — le message doit seulement tenir dans le DATA_PAYLOAD_LEN de Meshtastic, soit 233 octets.
Le mode de défaillance de Bitcoin est rarement le réseau lui-même — c’est votre connexion à lui. Une panne de fournisseur d’accès, une panne de courant ou de la censure pure et simple laisse l’opérateur de nœud aveugle : la chaîne avance-t-elle? Quel est le sommet? Combien coûterait une transaction en ce moment? Une balise répond à ces questions pour tout un mesh de quartier, depuis un nœud que vous contrôlez. C’est une infrastructure défensive : elle ne déplace aucune pièce et ne signe rien. Si vous voulez faire circuler de vraies transactions sur un mesh, c’est un travail différent (et plus difficile) — voir Bitcoin over Meshtastic : signer et diffuser des transactions hors réseau (en anglais) et Can I send bitcoins with mesh networks? (en anglais).
Ce que le protocole permet réellement
Chaque valeur ci-dessous est un littéral des sources Meshtastic (en date du 2026-07-22,
master) — rien ne vient d’un résumé, et les citations restent en anglais parce que ce sont
des extraits littéraux des fichiers sources. Meshtastic est une cible mouvante : revalidez ces constantes contre la
version que vous exécutez.
| Fait | Valeur littérale (en anglais) | Source |
|---|---|---|
| Charge utile texte maximale | DATA_PAYLOAD_LEN = 233 octets — « ONLY the bytes that are sent inside of the Data protobuf (excluding protobuf overhead). The 16 byte header is outside of this envelope » | meshtastic/protobufs → mesh.proto, enum Constants |
| Garde de longueur du CLI | if len(data) > mesh_pb2.Constants.DATA_PAYLOAD_LEN: lève "Data payload too big" | meshtastic/python → mesh_interface.py, sendData() |
Port utilisé par --sendtext | TEXT_MESSAGE_APP = 1 — « ENCODING: UTF-8 Plaintext »; sendText() utilise portNum = TEXT_MESSAGE_APP par défaut | portnums.proto; mesh_interface.py — voir le registre des PortNum |
| Adressage de diffusion | BROADCAST_ADDR = "^all" (destination par défaut du CLI Python); sur les ondes #define NODENUM_BROADCAST UINT32_MAX | meshtastic/python → __init__.py; meshtastic/firmware → src/mesh/MeshTypes.h |
| Limite de sauts | « Maximum number of hops. This can’t be greater than 7. Default of 3. Attempting to set a value > 7 results in the default » | config.proto → LoRaConfig.hop_limit |
| Sauts sur les ondes | hop_start : « Sent via LoRa using three bits in the unencrypted header » | mesh.proto → MeshPacket.hop_start |
En bref : une diffusion texte d’au plus 233 octets UTF-8 atteint chaque nœud à (par défaut) 3 sauts de votre balise, relayée par le mesh lui-même. C’est bien plus d’espace qu’un instantané d’état de chaîne n’en demande.
Ce qu’il vous faut
- Un nœud Bitcoin Core auto-hébergé avec
bitcoin-clifonctionnel en local. La balise ne fait que lire — aucun portefeuille requis. - Un nœud Meshtastic que la machine peut joindre — par USB série (
--port /dev/ttyUSB0) ou par WiFi/Ethernet (--host <ip>). Nouveau sur Meshtastic? Commencez par Meshtastic pour bitcoiners (en anglais). - Le CLI Python de Meshtastic (
pipx install meshtastic) etjqpour analyser le JSON debitcoin-cli. - Un canal secondaire dédié pour la balise (
--ch-index 1ou plus), pour que les données de chaîne récurrentes n’encombrent pas le canal principal où tout le monde clavarde.
Le script de la balise
Trois RPC en lecture seule, un message, une garde d’octets stricte. estimatesmartfee retourne des
BTC/kvB : multiplier par 100 000 donne des sat/vB; un nœud récent ou pauvre en données de frais
peut ne retourner aucune estimation, que le script dégrade en n/a au lieu d’échouer. Le script
est laissé tel quel, commentaires en anglais compris.
#!/usr/bin/env bash
# btc-beacon.sh — broadcast Bitcoin chain state over a Meshtastic LoRa mesh
set -euo pipefail
MESH_ARGS=(--host 127.0.0.1) # or: MESH_ARGS=(--port /dev/ttyUSB0)
CH_INDEX=1 # dedicated beacon channel — not 0 (the primary channel)
HEIGHT=$(bitcoin-cli getblockcount)
TIP=$(bitcoin-cli getbestblockhash)
FEE_BTC_KVB=$(bitcoin-cli estimatesmartfee 3 | jq -r '.feerate // empty')
if [ -n "$FEE_BTC_KVB" ]; then
# estimatesmartfee reports BTC/kvB; 1 BTC/kvB = 100000 sat/vB
FEE_SATVB=$(awk -v f="$FEE_BTC_KVB" 'BEGIN{printf "%.1f", f * 100000}')
else
FEE_SATVB="n/a"
fi
# Compact snapshot: height, last 12 hex chars of the tip hash, ~3-block fee, UTC time
MSG="BTC ${HEIGHT} tip ..${TIP: -12} fee3 ${FEE_SATVB} sat/vB $(date -u +%H%MZ)"
# Hard guard: TEXT_MESSAGE_APP payloads must fit DATA_PAYLOAD_LEN (233 bytes)
BYTES=$(printf '%s' "$MSG" | wc -c)
if [ "$BYTES" -gt 233 ]; then
echo "beacon message is ${BYTES} bytes (> 233), refusing to send" >&2
exit 1
fi
meshtastic "${MESH_ARGS[@]}" --ch-index "$CH_INDEX" --sendtext "$MSG"
Le budget d’octets
Le message d’exemple ci-dessus s’affiche, par exemple, ainsi :
BTC 909453 tip ..1a2b3c4d5e6f fee3 4.2 sat/vB 1840Z
C’est 51 octets (de l’ASCII pur, donc octets = caractères) — moins du quart du budget
DATA_PAYLOAD_LEN de 233 octets. Même une variante paranoïaque portant le hash complet du sommet en
64 caractères plus une date complète —
BTC 909453 tip 00000000000000000001c8a4e2f0b7d64a5f3e9b12c07d8f6a4b3e2d1c0f9a8b fee3 4.2 sat/vB 2026-07-22 1840Z
— fait 112 octets, encore confortablement sous la limite. La forme tronquée est habituellement le bon compromis : les derniers caractères hexadécimaux d’un hash de bloc sont les plus distinctifs (les premiers sont des zéros par construction), 12 suffisent amplement pour que deux humains comparent leurs balises, et des paquets plus courts consomment moins de temps d’antenne. Restez en ASCII — la limite est en octets, et les caractères UTF-8 multioctets grugent le budget plus vite qu’ils en ont l’air.
Planifiez-la avec systemd
Un service oneshot avec un minuteur bat une ligne cron ici : vous obtenez des journaux dans journalctl, de la
gigue via RandomizedDelaySec pour que des balises voisines n’entrent pas en collision, et aucune tempête
de balises après un redémarrage. Les fichiers d’unités sont laissés en anglais tels quels.
# /etc/systemd/system/btc-beacon.service
[Unit]
Description=Bitcoin chain-state beacon over Meshtastic
After=network.target
[Service]
Type=oneshot
User=bitcoin
ExecStart=/usr/local/bin/btc-beacon.sh
# /etc/systemd/system/btc-beacon.timer
[Unit]
Description=Run the Bitcoin Meshtastic beacon every 20 minutes
[Timer]
OnBootSec=2min
OnUnitActiveSec=20min
RandomizedDelaySec=90
[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now btc-beacon.timer
systemctl list-timers btc-beacon.timer
Soyez un bon voisin radio
- Cadence : pensez en dizaines de minutes, pas en secondes. Bitcoin produit en moyenne un bloc toutes les ~10 minutes; une balise aux 20–30 minutes suit la chaîne d’assez près pour un canal d’urgence tout en laissant du temps d’antenne aux humains. Le LoRa aux préréglages longue portée est lent — voir la référence des préréglages du modem (en anglais) pour ce qu’un paquet coûte sur les ondes.
- Respectez les règles radio de votre région. Les bandes de fréquences, le rapport cyclique et les limites de puissance varient selon la région et sont imposés dans le micrologiciel par code de région — nous gardons le tableau littéral par région (transcrit du
RadioInterface.cppdu micrologiciel) dans le jeu de données des régions et canaux LoRa (en anglais) plutôt que de le reformuler ici. - Utilisez un canal secondaire. Une balise sur
--ch-index 0inonde chaque appareil en configuration par défaut à portée. Un canal secondaire nommé rend la balise opt-in : les abonnés ajoutent le canal, et les radios des autres relaient quand même les paquets. - Laissez la limite de sauts à son défaut de 3 à moins que votre topologie en exige vraiment plus; le micrologiciel la plafonne à 7 et ramène silencieusement toute valeur supérieure au défaut.
Recevoir la balise — et rattraper le fil après une absence
Les récepteurs n’ont besoin de rien de spécial : tout appareil Meshtastic avec le canal de la balise configuré affiche chaque instantané comme un message texte normal — app téléphone, écran de l’appareil, ou nœud sans tête que vous scriptez. L’enveloppe dans laquelle voyage chaque paquet de balise est documentée champ par champ dans la référence MeshPacket & Data.
Une balise se marie naturellement avec un serveur Store & Forward :
parce que les balises sont de simples diffusions TEXT_MESSAGE_APP, un serveur S&F sur le même canal les
stocke, et un appareil qui était éteint peut rejoindre le mesh et rejouer l’historique récent (par
défaut jusqu’à 25 messages stockés des 4 dernières heures) — transformant
« qu’est-ce que j’ai manqué? » en une réponse en une requête, qui inclut le
dernier état de la chaîne.
Ce qu’une balise n’est pas
- Pas un portefeuille, pas un relais de transactions. Elle lit trois RPC et écrit un texte. Déplacer des transactions signées sur un mesh — et les acheminer vers un nœud capable de les diffuser — est couvert dans Bitcoin over Meshtastic (en anglais).
- Pas un consensus. Une balise rapporte la vue de la chaîne d’un seul nœud. Faites-lui confiance comme vous faites confiance à l’opérateur de ce nœud — idéalement, faites tourner votre propre balise et comparez. Deux balises indépendantes qui s’accordent sur un hash de sommet sont un signal fort; c’est pourquoi le message inclut des caractères du hash et pas seulement une hauteur.
- Pas privée. L’état de la chaîne est une donnée publique, et c’est exactement pourquoi il est sûr de la diffuser. N’étendez pas la balise à quoi que ce soit qui ressemble à un portefeuille ou à un solde.
Pourquoi ça compte pour la souveraineté
L’intérêt de faire tourner un nœud est de vérifier au lieu de faire confiance — mais une vérification que vous ne pouvez atteindre que par un seul fournisseur d’accès est une vérification avec un propriétaire au-dessus. Une balise LoRa est la sortie la moins coûteuse possible de cette dépendance : un opérateur de nœud avec une radio garde tout un mesh au courant de la chaîne pendant une panne, de la même façon que les communications d’urgence par mesh (en anglais) gardent les gens connectés quand l’infrastructure flanche. C’est une couche de la pile de souveraineté D-Central — Bitcoin et la radio mesh sont le même combat (en anglais).
Pages reliées
Pôle mesh souverain (en français) · Bitcoin over Meshtastic : transactions hors réseau (en anglais) · Registre des PortNum (en anglais) · Référence MeshPacket & Data · Référence Store & Forward · Régions et canaux LoRa (en anglais) · Montage d’un nœud Meshtastic solaire (en anglais).
Crédit à qui de droit : la couche mesh est l’œuvre du projet Meshtastic — micrologiciel, protobufs et le CLI Python (GPL-3.0) — et la couche nœud est Bitcoin Core (MIT). Cette page relie leurs outils avec un script shell; constantes citées en date du 2026-07-22.
Produits, réparations et guides connexes
- hub de souveraineté pour Bitcoiners
- la stack souveraine des plebs
- Nostr pour les Bitcoiners
- héberger votre propre relais Nostr
- débuter avec Meshtastic
- Bitcoin sur les réseaux mesh Meshtastic
- répertoire d’outils matériels open source
- minage Bitcoin hors réseau
Dernière révision: 23 juillet 2026.
