Development
It is the purpose of the node to broadcast transactions to other nodes and miners.
All code for node-specific actions and tools go in the /node
folder.
In order to develop parts of the blockchain that include communication between nodes and miners, it is important to populate the nodes.txt file with multiple IP entries. You will need at least 2 nodes running in order to test communication between them. You can do so by:
- Finding your external IP address
- Choosing a port for these nodes to run on. Ports 9999 and 9998 are a good option.
- You must port forward any ports you choose to use for your nodes. The miner runs on port 3333, make sure this port is being forwarded as well.
- In the nodes.txt file, make one entry per node that you expect to run. An example would look like:
63.123.1.43:9999
63.123.1.43:9998
63.123.1.43:9997
- Notice how all IPs are the same, only the ports are different.
- Start the node by running
thor node_launcher:port PORT
- Start another node (in a new terminal window) using
thor node_launcher:port PORT
- After starting one or more nodes, start the miner by running
ruby miner/miner.rb
. It is important to run this after your a node has already been run.
Nodes can be connected and notify each other uppon receiving new transactions. Connecting nodes via GET request:
http://0.0.0.0:9001/register_node?ip_with_port=CONNECTED_NODE_IP_HERE:CONNECTED_NODE_PORT_HERE
Or using irb:
require 'net/http
request = Net::HTTP.new(NODE_IP_HERE, NODE_PORT_HERE)
request.get('/register_node?ip_with_port=CONNECTED_NODE_IP_HERE:CONNECTED_NODE_PORT_HERE').body
As a response you'll see a confirmation node response with a node list:
{"nodes":[CONNECTED_NODE_IP_HERE:CONNECTED_NODE_PORT_HERE]}
After setting up your nodes, you may want to simulate a transaction between the nodes. A good way to test this is by popping open irb and running:
require 'yaml'
require 'net/http'
require_relative 'lib/transaction.rb'
def parameterize(params)
# Transforms a hash to a parameter string
# E.x. {a: 'something', b: 'otherthing'} => 'a=something&b=otherthing'
URI.escape(params.collect{|k,v| "#{k}=#{v}"}.join('&'))
end
tx = Base64.encode64(YAML::dump(Transaction.new(RECIPIENT_PUBLIC_KEY, AMOUNT)))
Net::HTTP.new(IP_ADDRESS_HERE, PORT_OF_ONE_OF_THE_NODES).post("/transactions/new", parameterize({transaction: tx})).body
The result should be a post request from one of the nodes to the others, notifying them of a new transaction.
Wallets are based on ECDSA encryption key pairs. To generate a keypair, pop open irb and run:
require_relative 'wallet/wallet.rb'
wallet = Wallet.new
After doing so, you should see a new .pem file in the wallet/keys folder. Furthermore, you can see your public key (wallet address) by typing wallet.public_key_hex
. It is often useful to generate a fake keypair when testing the blockchain (in order to send tokens to another address, for example). To do this, you can manually run the code in the wallet.rb file within the generate_ecdsa_keypair
method.
The miner processes transactions by storing them in blocks and running a hashing algorithm to create a proof-of-work.
All code for the miner goes in the /miner
folder.
The code behind the actual blockchain, such as the models for a block, chain, ledger, and transaction, are stored in /lib