Connection part one – Finding a node and packets routing
The first thing we need our code to do is to connect to the Bitcoin network. this is relatively straightforward process, we just need to find one node in the network and establish connection with that node. A list of few of the active nodes can be easily found online. We’ve randomly picked one node from this list on blockchain.info .
We’re using the socket module to establish our connection using this simple code:
import socket import sys HOST = "66.90.137.89" PORT = 8333 """ We will use this file to connect to one node But in the future we will connect to more than one """ def connect(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect((HOST, PORT )) except Exception as e: print e sys.exit(0) return sock
we’ve also created main.py
at the root of our folder structure (right under Bitpy/
). This will initialize the connection code upon startup and will route our incoming and outgoing packets to ReceiverManager
and SenderManager
respectively. The queue module helps us to make sure that the packets are being processed in the right order. We’ll later see what each file does, but for now, what is important to understand is:
- We’re connecting to another node on the network.
- We’ve found the address of this node on a public list at blockchain.info.
- The connection code is stored at
Network/connection.py
- We’ve created a Main file under our root directory (
Bitpy/Main.py
) that will initialize the connection to the node, and will route our incoming and outgoing packets to one of the two queues filesSenderManager.py
(for outgoing packets) andReceiverManager.py
(for incoming packets). Both files can be found underManager/
. - The user manually specify which packet (message) he wants to send using the
core_manager
. We’ll talk about it later on when we’ll be dealing with the user interface.
So now we should have a look at our Receiver/Sender Managers, but our ReceiverManager
is a bit too complex for this stage, so we’ll talk about it later, once we’re ready to talk about parsing incoming messages. For now, we’ll only have a look at our SenderManager
.
The first thing we did was to use the threading module. This module allows us to keep our connection asynchronous, that means that we can receive and send messages at the same time. Apart from this threading module this file contains only one more class – SendingManager
. Once this class is defined, it will have access to our thread, it will be able to use or sock
object (declared in connection.py
) to connect to the remote node and it will also receive the packets queue from the main.py
file.
from threading import Thread class SenderManager(Thread): def __init__(self,sock, queue): Thread.__init__(self) self.sock = sock self.queue = queue def run(self): while True: if not self.queue.empty(): order = self.queue.get() self.sock.sendall(order) print "Exit sender Thread"
So the main.py
file gets a list of packets (messages) from the user which he wishes to send. (The user creates the packets in the core_manager.py
file). The packets are stored in a queue, and a SenderManager
object is then created. It gets access to the sock
object, the thread
, and the queue
, then it will simply send the packets in their order, as specified in the queue
, one by one, to the ip address and port of the sock
, while making sure that the connection remains asynchronous.
Before we can start sending and receiving messages, we first need to learn about messages.