Skip to content

Development

Pavel Durov edited this page Jan 13, 2018 · 15 revisions

Node

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.

Dev Environment Setup

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:

  1. Finding your external IP address
  2. Choosing a port for these nodes to run on. Ports 9999 and 9998 are a good option.
  3. 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.
  4. 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
  1. Notice how all IPs are the same, only the ports are different.
  2. Start the node by running thor node_launcher:port PORT
  3. Start another node (in a new terminal window) using thor node_launcher:port PORT
  4. 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.

Connecting nodes

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]}

Simulating a Transaction

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.

Generating a wallet

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.

Miner

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.

Blockchain

The code behind the actual blockchain, such as the models for a block, chain, ledger, and transaction, are stored in /lib