Sunday, September 24, 2017

Sending Transactions in a private Ethereum Blockchain Network - Lou Person

Sending Transactions in a private Ethereum Blockchain Network - Lou Person

There are many ways to send transactions across a Blockchain network.  This post discusses how it is done using basic methods, such as sending from a software wallet and using send transactions from the command line.  These methods are essentially equivalent to “Hello World” applications to prove out that all pieces of the stack are successfully installed and properly communicating.  Transactions can also be sent programmatically through contracts written in Solidity on the Ethereum network, but that will be a later post. 

There are a few components to a distributed Blockchain system that enable transactions to be passed between accounts participating in the Blockchain. The components are:
  • The network itself. I have been using Ethereum primarily. You can create accounts on the network before the Blockchain is launched. A network can be private, where a node has to be invited in, or Public, where anyone can attach.
  • The Blockchain. A blockchain is initialized, or launched, on the network. A genesis.json file describes the Blockchain and currency can be allocated to accounts on launch if the account id is known.
  • Nodes. When a node is launched, it will download all the Blocks previously created on the Blockchain.
  • Accounts. An account contains an ID, cryptography key and a password. Wallets are developed around the accounts to make them easier to manage, as well as send transactions directly or through contracts.
  • Contracts. Contracts are created programmatically and used to transact within the network, between accounts. The Ethereum network uses Solidity as the programming environment.
  • Cryptocurrency. When a Blockchain is launched, accounts can be allocated currency. Alternatively, cryptocurrency can be mined on the network through an attached node and allocated to an account was successfully mined. In the Ethereum network, the currency are Ethers.
Here are some scenarios to piece all of this together: 

Created a 3 node Ethereum network
A 3 node Ethereum network was created, read more about it here: http://blog.louperson.com/2017/09/created-3-node-private-ethereum.html

Launch an Ubuntu Server on AWS, open the requisite ports and install putty
AWS makes all of this so easy, and frankly, if it wasn’t for the evolution of AWS as a Public Cloud provider, Blockchains would be much less credible. Blockchain requires always on, highly available and distributed computing resources. Using AWS to host Blockchain (in this case Ethereum nodes) provides a highly reliable, infinitely scalable, fully distributed, secure and cost effective platform. A few quick notes on AWS (most importantly the ports that are needed in the security group):

Create a root account and protect it with a hardware based MFA.
Create IAM accounts and enable soft MFA, try to work out of the IAM accounts and not root.
Create a Security Group, give it a meaningful name such as Blockchain, and make sure these inbound ports are open:
  • 30303, 35376, 30333 – Blockchain peering protocol (probably only 1 is needed if there is consistency when launching nodes) 
  • 22 – SSH 
  • 8545 – Used by Wallets and Contracts to talk to the nodes for account information 
At the time of writing, this Amazon Machine Image (AMI) was ideal: Ubuntu Server 16.04 LTS (HVM), SSD Volume Type - ami-6e1a0117
Select the Instance Type. The t2.micro free Tier should be fine, it can always be scaled up later, part of the beauty of AWS.
Select defaults under Instance details.
Create one volume of 30GB. General purpose SSD is fine.
Add tags as needed for administration, automation and reporting purposes, or leave blank.
Add the instance to the Security Group previously configured.
Review and launch.
Create an Elastic IP and assign it to the EC2 instance that was just launched.
Use an existing key pair or create a new one, but make sure it is downloaded and saved because it is required when connecting to the server. The .pem file is required to be downloaded before the server is launched.
Connect to the server using Putty or other ssh client, instructions for Putty here: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/putty.html
Install the following on the server:
  • sudo apt-get install software-properties-common 
  • sudo add-apt-repository -y ppa:ethereum/ethereum 
  • sudo apt-get update 
  • sudo apt-get install ethereum
Create the Genesis.json file and initialize the node
It’s best to keep this file as simple as possible.  Use the alloc statement to allocate ethers to a few accounts initially, but this isn’t necessary, in fact, it adds complexity to the Genesis.json file.
{
    "config": {
        "chainId": 15,
        "homesteadBlock": 0,
        "eip155Block": 0,
        "eip158Block": 0
    },
    "nonce": "0x0000000000000042",
    "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "difficulty": "0x4000",
    "alloc": {},
    "coinbase": "0x0000000000000000000000000000000000000000",
    "timestamp": "0x00",
    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "gasLimit": "0xffffffff",
    "alloc": {
        "aba11d916475e---------a9b916----97b9508e": { "balance": "20000000000000000000" },
        "31e3575b7----------29634fb8053----02fbbab": { "balance": "40000000000000000000" },
        "c5f995a---------0a9f20db650fb142----e698": { "balance": "40000000000000000000" }

    }
}
Initialize the node: $geth init Genesis.json

Create a shell file to launch the network with this command:
nohup geth -rpc --rpcaddr "0.0.0.0" --rpcapi personal,web3,eth --networkid 23 --nodiscover --maxpeers 10  --port 30303 &
Call the file rungeth.sh and did a chmod 775 rungeth.sh on it so it is executable as  .\rungeth.sh
Use the following command to list all the accounts in the network, of which there were none at launch:
geth account list rpc:http://localhost:8545

Create accounts directly on the primary node using Mist
Install mist on the client-side machine.  By doing so, the entire Blockchain doesn’t need to be downloaded directly, which saved space.  Also, any mining work will be done on the remote server on which the node is running, so much thinner hardware can be used on the client side.
Then, connect to the main node:
mist --rpc http://54.68.50.219:8545 --swarmurl=http://swarm-gateways.net
Once attached, hit the Add Account button, create the account and give it a password.  Add a few accounts for experimentation purposes in the sections below.  The key will be stored on the server side.  Once the account is created, list the accounts and the new account will appear (this command is not sent through the geth console):
$ geth account list rpc:http://localhost:8545
Account #0: {aba11d916475e48----------91640d997b9508e} keystore:///home/ubuntu/.ethereum/keystore/UTC--2017-09-22T19-43-46.697950494Z--aba11d916475e4----------640d997b9508e
Account #1: {f201d1ac0ec3a64f82e9----------93c1890} keystore:///home/ubuntu/.ethereum/keystore/UTC--2017-09-23T15-16-18.421518845Z--f201d----------f82e9a54c11d6ffb9f93c1890
Account #2: {3bd8646cc9----------f8812d670ea607687a05} keystore:///home/ubuntu/.ethereum/keystore/UTC--2017-09-23T22-24-57.228977892Z--3bd86----------52063f8812d670ea607687a05
This also lists accounts from the geth console: >eth.accounts

Mine Ethers into the account
With geth running in the background, attach to the console:
$geth attach
Set the account that you want to mine into referencing the account list above:
> miner.setEtherbase(eth.accounts[1])
Launch the miner:
>miner.start(10)
Note that 10 is the number of threads that will be used for mining, another benefit of working with AWS so the requisite processing is available.
After sufficient Ethers are added to the account, about 1000, switch wallets:
> miner.setEtherbase(eth.accounts[2])
When done, stop the miner:
>miner.stop()

Ethers will now appear in the account on the Mist wallet.  For the other sections below, add Ethers to all the accounts created.

Checking account balances
The following command is used to check balances of the accounts.  The number after eth.accounts represents the number of the account for which the balance is being queried:
> balance = web3.fromWei(eth.getBalance(eth.accounts[0]), "ether");

Send Transactions using Mist
In the Mist wallet, select one of the accounts that Ethers will be sent from, enter an account that Ethers will be sent to.  Using the account list above, this example used this account:
3bd8646cc9----------f8812d670ea607687a05
Enter an amount.
Hit send.

On the geth console on the server, view the pending transaction:
>eth.pendingTransactions
Here is what the pending transaction will look like:
[{
    blockHash: null,
    blockNumber: null,
    from: "0xaba11d916475e48----------91640d997b9508e",
    gas: 121001,
    gasPrice: 18000000000,
    hash: "0x21c8720e4ec5885---------------4f1e33870f3db0576ede88bea50529d96d",
    input: "0x",
    nonce: 2,
    r: "0xe0ad06721af4be89e87239---------------31b3e9cb2c9abf07dde41e7cd9c",
    s: "0x7cadeb998790304009fb---------------0f25178df8f4c008f139cedd3dddc",
    to: "0x3bd8646cc9----------f8812d670ea607687a05", transactionIndex: 0,
    v: "0x41",
    value: 200000000000000000000
}]
Enter this command to post the transactions: 
> miner.start();admin.sleepBlocks(1);miner.stop();

The pending transaction queue will go to null and the Ethers will be transferred between wallets.
Check the account balances using:
> balance = web3.fromWei(eth.getBalance(eth.accounts[0]), "ether");
> balance = web3.fromWei(eth.getBalance(eth.accounts[2]), "ether");

Send Transactions using the SendTransaction command
From the geth console, use the SendTransaction command to send Ethers between two accounts as follows:
First, unlock the seconding account:
personal.unlockAccount("'aba11d916475e48----------91640d997b9508e'")

Then, send the transaction.
>eth.sendTransaction({from: '0xaba11d916475e48----------91640d997b9508e', to: ' f201d1ac0ec3a64f82e9----------93c1890', value: web3.toWei(23, "ether")})

Check it is pending: >eth.pendingTransactions
This command is needed to execute the transaction:
> miner.start();admin.sleepBlocks(1);miner.stop();

Adding a node to the Blockchain
On the first node, run this command from the geth console to get the node information:
>admin.nodeInfo.enode
Copy and paste what is returned, changing the [::] to the public IP address of the server.

To add an independent node to the Blockchain, launch geth on the second server and then run this command, replacing the text after enode:// and the IP address with the correct values of the real environment, sample data is used:

admin.addPeer("enode:// be89ed26d4bc95e2bf7e388a8ec--------------------7f8b5ef80a2bb7e62dd2de6dd03d8cff6609570eb--------------------1bf404ca1ae3659f0149@54.22.33.169:35376?discport=0")
Wait a few seconds, then on both servers run
>net.peerCount
and each should return 1 indicating the nodes are connected.

Launching another node into the network using a Bootloader
Setup another server per the instructions above and initialize it using the same Genesis.json file.
On the first node, run this command from the geth console to get the node information:
>admin.nodeInfo.enode
Copy and paste what is returned, changing the [::] to the public IP address of the server.
On the main server, enter this:
>net.peerCount which should return 0 because the second node is connected yet.
On the second node, launch geth by attaching to the Bootloader as follows:
geth  --networkid 23 --bootnodes enode://be89ed26d4bc95e2bf7e388a8ec--------------------7f8b5ef80a2bb7e62dd2de6dd03d8cff6609570eb--------------------1bf404ca1ae3659f0149@54.22.33.169:30303 console

Wait a few seconds, then on both servers run
>net.peerCount
and each should return 1 indicating the nodes are connected.

Create a new account on the second node:
>personal.newAccount()

On the second node, list the accounts to confirm the account was created
> eth.accounts
["0x6fd643e5------------5ec78423be-----0f9d4"]

On the second node, list the balance of the account, it should be 0 because it was just created:
> balance = web3.fromWei(eth.getBalance(eth.accounts[0]), "ether");

With the two nodes created, send a transaction from the from an account on the first node to the account on the second node.  The account on the second node will not be visible directly on the first node, it needs to be explicitly entered.  This is due to the second node managing the keystore of the accounts associated with that node.  However, since the two nodes are connected, transactions can be sent between them.
>eth.sendTransaction({from: 'aba11d916475e48----------91640d997b9508e ', to: '0x6fd643e5------------5ec78423be-----0f9d4', value: web3.toWei(500, "ether")})

List pending transactions:
> eth.pendingTransactions

On the first node, post the transaction:
>miner.start();admin.sleepBlocks(1);miner.stop();

On the second node, check the balance and the ethers should have posted across the nodes:
> balance = web3.fromWei(eth.getBalance(eth.accounts[0]), "ether");
500

What comes next
Later posts will describe how to post transactions using programmatic contracts, as well as what is happening behind the scenes, such as authorizations from all nodes on the Blockchain.


No comments:

Post a Comment