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:
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
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:
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.