Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johnshearing/9a967dc408116e738c2e6d723acf1822 to your computer and use it in GitHub Desktop.
Save johnshearing/9a967dc408116e738c2e6d723acf1822 to your computer and use it in GitHub Desktop.

Everything about working with the Ethereum blockchain is found here at DecypherTV videos

These are notes for the fourth video

This video first shows how to make unsigned transactions by unlocking your account. Then a more secure method is shown for creating signed transactions in a secure local environment and then sending them to a test blockchain without ever having your account unlocked and without ever exposing your private key to the Internet.

Make a Local BlockChain

See my instructions for making a local blockchain and for setting up accounts. In the alternative you can use testrpc. If you are using a local block chain then you will need to create 4 accounts in order to experiment with the transactions in this exercise and you will need to mine some play ether into your first account to pay for your transactions. This is all covered at the link above.

Setup the WorkFolder Environment

Setup is the same as in notes for video 2 with one added dependency.
All the Node dependencies are listed as follows

// package.json
{
  "dependencies": {
    "web3": "0.17.0-alpha",
    "ethereumjs-util": "4.5.0",
    "ethereumjs-tx": "1.1.2"
  }
}

Changing the Prompt if you are using PowerShell

If you are using PowerShell as the operating system's command line interpreter you can change the prompt with the following command if desired. Remember to add a space at the end of the prompt for reading ease:
Function prompt {“My Prompt> “}

Start Geth

I put a copy of geth.exe in my project directory.
Run the following commands one at a time in your OS command line interpreter.
Of course you would change the path names in the commands to suit your environment.

cd C:\Users\John\BlockChain\Ethereum\WorkFolder\Decypher_TV\Transactions  

function prompt{"Run Chain> "}  

./geth --networkid 1100 --identity JohnsComputer --nodiscover --nat none --datadir C:\Users\John\BlockChain\TestChainDataFiles --rpc --rpcapi "db,eth,net,web3" --rpccorsdomain "http://localhost:8545" console

Initializing the Environment

Next I start a second instance of my OS command line interpreter and run the commands one at a time.

cd C:\Users\John\BlockChain\Ethereum\WorkFolder\Decypher_TV\Transactions  

node

Now the Node console is running in my project directory.
Remember that ctrl + L clears the Node console of clutter.

Make Node aware of the web3 library.
var Web3 = require("web3")
The Node console will return undefined.

Create an instance of the web3 library within Node and connect it to TestRPC or to your local blockchain (whichever is running).
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"))

Basic commands for account information

Now run the following command to see the accounts availalble. :
web3.eth.accounts
You should see the wallet addresses of all the accounts.

Now run the following command to see the address of the first account only.
web3.eth.accounts[0]

To see the balance of the account in Wei run the following command.
web3.eth.getBalance(web3.eth.accounts[0])

To see the balance in Ether
web3.fromWei(web3.eth.getBalance(web3.eth.accounts[0]), 'ether')

To see the balance in Ether as a number run the following:
web3.fromWei(web3.eth.getBalance(web3.eth.accounts[0]), 'ether').toNumber()

Unlocking Your Accounts with unlockAccount

If you are using a local blockchain it will be necessary to unlock your accounts before you can transfer funds.
It seems this cannot be done using web3 for security reasons.
To do this open a new instance of your operating system's CLI (Command Line Interpreter)
Navigate to a directory that contains geth.exe and execute the following command:
./geth attach
This opens a more secure JavaScript console for working with accounts on your local machine.
Read more about geth's Javascript console here.
To unlock your accounts execute the following command for each account to be unlocked.
personal.unlockAccount(web3.eth.accounts[0], "Password")

Making functions to reduce screen clutter at the Node console.

Back at the Node console run the following commands one at a time.
var acct1 = web3.eth.accounts[0]
var acct2 = web3.eth.accounts[1]
var acct3 = web3.eth.accounts[2]
var acct4 = web3.eth.accounts[3]
Now the accounts can be accessed with just a couple of characters.
The console will return undefined after each command is executed.

Run the following command to have a short means of accessing the balance of an account.
var balance = (acct) => { return web3.fromWei(web3.eth.getBalance(acct), 'ether').toNumber()}
The Node console will return undefined

To verify that the function works: enter the following command into the Node console and Press Enter.
balance(acct1)
The Node console will return the amount of ether in the account.
Notice that acct1 corresponds to account[0] because we declared the variable "acct1" as accounts[0].

Sending a Transaction with sendTransaction

Make sure the senders account is unlocked as shown above.
Then execute the following command to send 1 ether from acct1 to acct2.
In order for the command to work the gas price must be set to at least the going rate set by the mining community. This is not an issue when playing with a local blockchain.

web3.eth.sendTransaction({from: acct1, to: acct2, value: web3.toWei(1, 'ether'), gasLimit: 21000, gasPrice: 20000000000})

The Node console with return a transaction hash we will need that shortly.

The following command will save the hash as a variable.
var txHash = _
The cool thing to notice here is that the underscore character is used as a proxy for the output of the previous command.

Mining the Transaction

If you're using a local blockchain you will need to mine the transaction in order to get it into the blockchain. If you are using TestRPC or working on a blockchain with many active nodes then the mining is being done for you. It is not possible to activate the miner using the web3 interface so the Node console will not work for this. You will need to use geth's JavaScript console instead. If you are following along then you should have two open right now. One of them is the OS CLI that we used to start the blockchain. This became a JavaScript console when we started the blockchain because we used the console keyword in the command. The other is the one we used to unlock the accounts.
From either console execute the following command.
miner.start(1)
After the DAG file is built (this takes a while) the miner will start mining transactions. After a couple of blocks have been mined you can stop the miner, although here is no harm if you let it continue to run other then it chews up CPU cycles. miner.stop()

Examining the results of the transaction

Checking the Balances

Now from the Nodejs console you should be able to execute the following commands to see how much is in the various accounts. balance(acct1), balance(acct2)...

The toWei functions produces a string

Next in the Video at 4' 38" Jordan is discussing the cost of the transactions. This is a non issue for my local blockchain but he uses a function parseint() that gets the balance which converts from a string to an integer. What is interesting about this is that the toWei function produces a string not an integer as one might expect.
Here is the function below.
parseInt(web3.toWei(balance(acct1)))

Executing a variable name at the Node console.

At 5' 34" into the video we see Jordan types the variable name txHash at the Node console and presses Enter.
The output is the contents of the variable.
Executing a variable name at the Node console produces the contents of the variable. I didn't know you could do that.

How to get information about the transaction

Execute the following command.
web3.eth.getTransaction(txHash)
The Node console outputs a JavaScript object with information about the transaction.

The Nonce

6' 12' into the video.
The nonce is an auto-incrementing number. An address can only send a transaction with a particular nonce once.
This is used to keep an address from sending duplicate transactions.
A nonce can be passed into a transaction as an optional parameter.
There are experimental uses for sending transactions with nonces higher than the current value

Using the nonce to determine the amount of transactions an account has made.

web3.eth.getTransactionCount(acct1)

Code Abstraction can be viewed in logs

8' 42" into the video.
The web3 interface is a high level abstraction of lower level calls to geth. This makes it easier to get things done but some functionality is lost. The lower level calls made by web3 to geth can be viewed in the logs. In order to see these I would likely need to start geth with the various logging options

Signing Transactions

9' 28" into the video
For better security, sign a transaction off line with a private key, transfer the transaction to an online computer and then send the transaction. This keeps the private key off the online computer for greater security.
To accomplish this you will need to know the private key for one of your accounts. If you are using TestRPC they are given to you as shown in the video. If you are using a local blockchain it is impossible to know the private key unless you imported it yourself as described in my notes from an earlier video which can be found here.
I know that the private key for Account #3 is as follows:
b68fe43f0d1a0d7aef123722670be50268e15365401c442f8806ef83b612976b
This is the sha3 hash of the string "password".

The procedure is as follows:
Start by storing your private key as a variable.
Execute the following line of code:
var pKey1 = "b68fe43f0d1a0d7aef123722670be50268e15365401c442f8806ef83b612976b"

Next, tell Node where to find the Ethereum transaction library.
Execute the following line of code:
var EthTx = require("ethereumjs-tx")

The transaction library requires that data be passed in via JavaScript buffer instead of a string.
Execute the following command to convert the private key string stored in pkey1 to a JavaScript Buffer.
var pKey1x = new Buffer(pKey1, "hex")

Let's see what the buffer looks like.
Execute the following line of code:
pKey1x
The Node console will show the private key with characters paired up. Apparently, that's what a buffer looks like.

Create a raw transaction data structure and sign it with the private key.
We are creating a JavaScript object of key/value pairs with all integers converted to hexadecimal.
Copy and paste the entire following block of code into your Node console and execute.

var rawTx = {
   nonce: web3.toHex(web3.eth.getTransactionCount(acct4)),  
   to: acct2,  
   gasPrice: web3.toHex(20000000000),  
   gasLimit: web3.toHex(21000),
   value: web3.toHex(web3.toWei(25, "ether")),
   data: ""
}     

Now execute the variable to see what the object looks like.
type rawTx and press Enter.
The Node console will output something like the following:

{ nonce: '0x0',
  to: '0x5872dfbcbeebb2ebaef611d8a5668fe5c554bab0',
  gasPrice: '0x4a817c800',
  gasLimit: '0x5208',
  value: '0x15af1d78b58c40000',
  data: '' }  

Notice the integers have been converted to hexadecimal as planned.

Next we a transaction by feeding the data structure object we just made into the ethereumjs-tx library and save it to a variable.
Execute the following command to accomplish that.
var tx = new EthTx(rawTx)
The Node console returns undefined.

Now we sign the transaction using the buffer made from our private key.
Execute the following line of code. tx.sign(pKey1x)
The Node console returns Undefined

Now we can see what the signed transaction looks like by running it through the serialize function. Execute the following line of code. tx.serialize().toString("hex")
The Node console returns a very long hexadecimal string that represents the transaction.
Congratulations! Now we have a signed transaction. We can do all of this on a secure computer keeping our private key safe from crackers and then run the signed transaction on a different computer connected to the Internet (a non-secure computer exposed to crackers) and still be sure that our private key is safe and we can be sure that if the transaction does go through it will go through as instructed by the programmer.

Finally, we will append a "0x" to the beginning of the raw transaction string and then send the whole thing to the blockchain asynchronously using a call-back function as follows.
Execute the following line of code.

web3.eth.sendRawTransaction(`0x${tx.serialize().toString("hex")}`, (error, data) => {
   if(!error) { console.log(data) }
   else { console.log(error) }
   })

The if the transaction goes through then the Node console returns undefined and under that a long hexadecimal string - that's the transaction hash. My transaction hash was as follows:
0xf68a68ab772193aa5eb55b631a4b2e850b0c5ca1a7d91da663fa823879448f56
If there was a problem the the Node console returns the error message.

Cool: No need to unlock the account!

If your are using testRPC you don't have to unlock your account before sending a normal unsigned transaction but if you are using a local blockchain or running on a public blockchain the account must be unlocked before a transaction will go through and this is a pain because as seen above in these notes unlocking the account requires opening a separate JavaScript console with Geth attach and then executing the command personal.unlockAccount(web3.eth.accounts[0], "Password") to unlock the account from there. But when using a signed transaction there is no need to unlock the account. There are security issues associated with unlocked accounts as noted here. The biggest security advantage to creating signed transactions is that you can create them offline with an air-gapped computer. An air-gapped computer is a computer which is not connected to the Internet. This greatly reduces the chances that hackers will see your private key.

Since I am using a local blockchain I need to start the miner and mine a couple of blocks. This will get the transaction into the block chain.

We can use the transaction hash to see information about the transaction as follows.
Execute the following command at the Node console:
web3.eth.getTransaction("0xf68a68ab772193aa5eb55b631a4b2e850b0c5ca1a7d91da663fa823879448f56")
I executed this command two times: Once before mining the transaction and once after.
The following is what the transaction looked like before starting the miner:

web3.eth.getTransaction("0xf68a68ab772193aa5eb55b631a4b2e850b0c5ca1a7d91da663fa823879448f56")
{ blockHash: '0x0000000000000000000000000000000000000000000000000000000000000000',
  blockNumber: null,
  from: '0x9d39856f91822ff0bdc2e234bb0d40124a201677',
  gas: 21000,
  gasPrice: { [String: '20000000000'] s: 1, e: 10, c: [ 20000000000 ] },
  hash: '0xf68a68ab772193aa5eb55b631a4b2e850b0c5ca1a7d91da663fa823879448f56',
  input: '0x',
  nonce: 0,
  to: '0x5872dfbcbeebb2ebaef611d8a5668fe5c554bab0',
  transactionIndex: null,
  value: { [String: '25000000000000000000'] s: 1, e: 19, c: [ 250000 ] } }

And this is what the transaction looked like after the transaction was mined.

 web3.eth.getTransaction("0xf68a68ab772193aa5eb55b631a4b2e850b0c5ca1a7d91da663fa823879448f56")
 blockHash: '0xd637ab4bd92ebcf85d5b7073c39b6105ee56da84c2b7b6d5c125c21dda5035fa',
 blockNumber: 173,
 from: '0x9d39856f91822ff0bdc2e234bb0d40124a201677',
 gas: 21000,
 gasPrice: { [String: '20000000000'] s: 1, e: 10, c: [ 20000000000 ] },
 hash: '0xf68a68ab772193aa5eb55b631a4b2e850b0c5ca1a7d91da663fa823879448f56',
 input: '0x',
 nonce: 0,
 to: '0x5872dfbcbeebb2ebaef611d8a5668fe5c554bab0',
 transactionIndex: 0,
 value: { [String: '25000000000000000000'] s: 1, e: 19, c: [ 250000 ] } }

So the getTransaction function can be used to check whether or not a transaction has been mined and included in the blockchain.
Checking the balance of the two accounts also works.

Notes on Video 6 in the Series Are Found Here
More Resources for learning Etherum Are Found Here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment