├── Meshtastic to Bitcoin Core.py ├── README.md └── photos ├── Bridge01.png ├── Bridge02.png ├── Bridge03.png ├── Bridge04.png ├── Bridge05.png ├── Bridge06.png ├── Bridge07.png ├── Bridge08.png ├── BridgeBytes.png └── a.txt /Meshtastic to Bitcoin Core.py: -------------------------------------------------------------------------------- 1 | #pip3 install requests, pyserial and meshtastic 2 | #make sure you defind the devPath. search for it in the code and change it to your Meshtastic device's devPath (example COM5 or similar for Windows, /dev/ttyUSB0 or similiar for Linxu) 3 | import requests 4 | import json 5 | import subprocess 6 | import serial 7 | import meshtastic 8 | import meshtastic.serial_interface 9 | from pubsub import pub 10 | import time 11 | import datetime 12 | from decimal import Decimal 13 | 14 | 15 | RECVSTR = "" 16 | datainput2 = "" 17 | MANUALBTCTRANS = "" 18 | MANUALBTCTR = "" 19 | BTCBROAD = "" 20 | 21 | #-----------------------------------------------------------DEFINE FUNCTIONS ------------------------------------------- 22 | 23 | #LORA RADIO INITIALIZATION 24 | def onReceive(packet, interface): # called when a packet arrives 25 | global RECVSTR 26 | global MANUALBTCTRANS 27 | global MANUALBTCTR 28 | global datainput2 29 | RECVSTR = str(packet['decoded']['text']) 30 | print("") 31 | print(RECVSTR) 32 | print("") 33 | interface.sendText("rcvd..") 34 | if "==" in RECVSTR: 35 | interface.sendText("FIN!") 36 | RECVSTR = RECVSTR.replace("+","") 37 | RECVSTR = RECVSTR.replace("=","") 38 | MANUALBTCTRANS += RECVSTR 39 | MANUALBTCTR = MANUALBTCTRANS 40 | print("") 41 | print(MANUALBTCTR) 42 | print("") 43 | print("Length:"+str(len(MANUALBTCTR))) 44 | if len(MANUALBTCTR) > 0: 45 | try: 46 | interface.sendText("Length:"+str(len(MANUALBTCTR))) 47 | except Exception: 48 | print(f"failed") 49 | if "+" in RECVSTR: 50 | interface.sendText("cont...") 51 | RECVSTR = RECVSTR.replace("+","") 52 | MANUALBTCTRANS += RECVSTR 53 | print("") 54 | print(MANUALBTCTRANS) 55 | print("") 56 | if len(MANUALBTCTRANS) > 0: 57 | try: 58 | interface.sendText("Length:"+str(len(MANUALBTCTRANS))) 59 | except Exception: 60 | print(f"failed") 61 | 62 | if "-clear-" in RECVSTR: 63 | BTCBROAD = "" 64 | BTCSEND = "" 65 | MANUALBTCTR = "" 66 | MANUALBTCTRANS = "" 67 | interface.sendText("Code cleared!") 68 | 69 | if "-mempool-" in RECVSTR: 70 | MEMPOOL = subprocess.getoutput("curl -sSL \"https://mempool.space/api/v1/fees/recommended\"") 71 | MEMjson = json.loads(MEMPOOL) 72 | MEMCHECK = str(MEMjson['halfHourFee'])+" Sats/vByte" 73 | print(MEMCHECK) 74 | interface.sendText(MEMCHECK) 75 | 76 | 77 | 78 | def onConnection(interface, topic=pub.AUTO_TOPIC): # called when we (re)connect to the radio 79 | # defaults to broadcast, specify a destination ID if you wish 80 | interface.sendText("hello mesh") 81 | print(f"Lora Online") 82 | 83 | 84 | 85 | 86 | #TRY LORA RADIO CONNECTION 87 | #try: 88 | pub.subscribe(onReceive, "meshtastic.receive.text") 89 | pub.subscribe(onConnection, "meshtastic.connection.established") 90 | interface = meshtastic.serial_interface.SerialInterface(devPath='COM8') #you need to input your devPath (windows will be COM# like COM5, linux something like /dev/ttyUSB0 91 | #except Exception: 92 | # print(f"Lora not initialized") 93 | 94 | 95 | 96 | #BEGIN MAIN LOOP WAITING FOR USER INPUT ------------------------------------------------------------ 97 | then = datetime.datetime.now() 98 | while True: 99 | time.sleep(0.25) 100 | 101 | #CHECK FOR LORA COMMS 102 | now = datetime.datetime.now() 103 | if now.minute - then.minute > 5: 104 | then = datetime.datetime.now() 105 | try: 106 | pub.subscribe(onReceive, "meshtastic.receive.text") 107 | pub.subscribe(onConnection, "meshtastic.connection.established") 108 | interface = meshtastic.serial_interface.SerialInterface(devPath='COM8') #YOU need to input your devPath (windows will be COM# like COM5, linux something like /dev/ttyUSB0 109 | except Exception: 110 | print(f"Lora comms not reestablished") 111 | 112 | if len(MANUALBTCTR) > 20: 113 | BTCSEND = "/whateverpathyouhave/bitcoin-cli sendrawtransaction "+MANUALBTCTR #YOU NEED TO SPECIFY CLI COMMAND PATH 114 | interface.sendText("BTC Transaction Attempt Broadcast!") 115 | try: 116 | BTCBROAD = subprocess.getoutput(BTCSEND) 117 | print(BTCBROAD) 118 | if len(BTCBROAD) > 0: 119 | SENDTHIS = BTCBROAD.strip() 120 | if len(SENDTHIS) > 200: 121 | interface.sendText(SENDTHIS[0:199]) 122 | else: 123 | interface.sendText(SENDTHIS) 124 | BTCBROAD = "" 125 | BTCSEND = "" 126 | MANUALBTCTR = "" 127 | MANUALBTCTRANS = "" 128 | except Exception: 129 | BTCBROAD = "" 130 | BTCSEND = "" 131 | MANUALBTCTR = "" 132 | MANUALBTCTRANS = "" 133 | interface.sendText("Error! Message -clear- and Retry") 134 | 135 | 136 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Meshtastic BitcoinCore Bridge 2 | Broadcast Raw Transactions over Meshtastic Lora to a computer with Bitcoin Core 3 | 4 | # Use Case 5 | https://gotenna.com/blogs/newsroom/blockstream-satellite-and-gotenna-collaborate-to-make-sending-bitcoin-without-internet-possible 6 | 7 | Blockstream demonstrated how to use Bitcoin Core without users needing an internet or cellular connection. The machine running Bitcoin Core connected to a Blockstream Satellite and received transaction information via Lora Radios (goTenna). 8 | 9 | My challenge was to send raw transactions for broadcasting over Lora, but using Meshtastic. Meshtastic's apps have a maximum buffer of 228 bytes (approximately 228 characters), but raw hex for bitcoin core transactions may be more than 1000 characters. This python file will interpret the "+" and "==" to construct long strings to broadcast the transaction. 10 | 11 | Here is the example of the maximum buffer, thus why you need a string constructor like this python file. 12 |
13 | ![Stuff](https://github.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/blob/main/photos/BridgeBytes.png?raw=true) 14 | 15 | # Necessary Devices 16 | To Receive and Broadcast a Transaction 17 | * A computer running Bitcoin Core 18 | * A Meshtastic device connected over USB serial to the same computer. 19 | 20 | To transmit a Transaction over Lora 21 | * Another Meshtastic device 22 | 23 | # Instructions 24 | Bitcoin Core and Meshtastic already have great tutorials. If you don't know how to use Python, please go and find some training for this. If you do know how to use python, simply pip or pip3 install the Meshtastic, pyserial and requests python libraries if you do not have them installed. Then you can run the python file included. 25 | 26 | You will need to edit the Python file to specify the USB device path and also the CLI path (search the file, there are comments to show you where) 27 | 28 | # Commands 29 | * **-mempool-** : Ask the Bitcoin Core machine for the latest midpoint of fees. This will help you construct your raw transaction offline, especially helpful if you have an offline phone wallet. 30 | * **\+** : Add the + symbol and then approximately 200 characters of the raw transaction hex to start constructing the long string 31 | * **\==** : Add == to terminate the string and send the transaction 32 | * **-clear-** : If you make a mistake, you can clear the string and start over 33 | 34 | # Example 35 | 36 | **Begin by taking your raw transaction hex and dividing it into portions 200 characters or less and add a + sign to the text.** 37 |
38 | ![Stuff](https://github.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/blob/main/photos/Bridge01.png?raw=true) 39 |

40 | **The very last portion of the hex should have two equal signs == after it to finish the string construction.** 41 |
42 | ![Stuff](https://github.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/blob/main/photos/Bridge02.png?raw=true) 43 | 44 |

45 | **When the Python program begins, it sends out the message "hello mesh" to all who are on the connected device's Mesh network.** 46 | 47 | **Optional : By sending the message -mempool- , you can check the mempool's "midpoint" of fees to properly account for fees before creating a raw transaction. Every time the python program interacts with your messages sent over Meshtastic, you will see it reply "recvd.." to note that your message has been received.** 48 |
49 | **Begin sending pieces of your raw transaction with the + sign as you constructed in prior steps. Send them in order! And wait until you see the reply "recvd.." and the following character count, like you see below as Length:204 (this will vary for you).** 50 |
51 | ![Stuff](https://github.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/blob/main/photos/Bridge03.png?raw=true) 52 | 53 |

54 | **After receiving the confirmation of the length of the long string you are constructing, you can keep adding portions of the raw transaction...** 55 |
56 | ![Stuff](https://github.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/blob/main/photos/Bridge05.png?raw=true) 57 | 58 |

59 | **When you reach the last line of the raw transaction, you need to use two equal signs == to terminate it and broadcast the transaction. You will see the "FIN!" message that signifies it will try to broadcast the transaction.** 60 |
61 | ![Stuff](https://github.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/blob/main/photos/Bridge06.png?raw=true) 62 | 63 |

64 | **If there is an error, you will see a message from Bitcoin Core or the computer like this...** 65 |
66 | **How do you fix when you make an error? You just type in -clear- and start over.** 67 |
68 | ![Stuff](https://github.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/blob/main/photos/Bridge07.png?raw=true) 69 | 70 |

71 | **If the broadcast is successful, you will see a message from Bitcoin Core or the computer like this...** 72 |
73 | ![Stuff](https://github.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/blob/main/photos/Bridge08.png?raw=true) 74 | 75 | 76 | -------------------------------------------------------------------------------- /photos/Bridge01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/7f483e0b878552a8d6e32b4c1b702a0e80b273a5/photos/Bridge01.png -------------------------------------------------------------------------------- /photos/Bridge02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/7f483e0b878552a8d6e32b4c1b702a0e80b273a5/photos/Bridge02.png -------------------------------------------------------------------------------- /photos/Bridge03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/7f483e0b878552a8d6e32b4c1b702a0e80b273a5/photos/Bridge03.png -------------------------------------------------------------------------------- /photos/Bridge04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/7f483e0b878552a8d6e32b4c1b702a0e80b273a5/photos/Bridge04.png -------------------------------------------------------------------------------- /photos/Bridge05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/7f483e0b878552a8d6e32b4c1b702a0e80b273a5/photos/Bridge05.png -------------------------------------------------------------------------------- /photos/Bridge06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/7f483e0b878552a8d6e32b4c1b702a0e80b273a5/photos/Bridge06.png -------------------------------------------------------------------------------- /photos/Bridge07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/7f483e0b878552a8d6e32b4c1b702a0e80b273a5/photos/Bridge07.png -------------------------------------------------------------------------------- /photos/Bridge08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/7f483e0b878552a8d6e32b4c1b702a0e80b273a5/photos/Bridge08.png -------------------------------------------------------------------------------- /photos/BridgeBytes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BTCtoolshed/MeshtasticBitcoinCore_Bridge/7f483e0b878552a8d6e32b4c1b702a0e80b273a5/photos/BridgeBytes.png -------------------------------------------------------------------------------- /photos/a.txt: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------