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/b0c87c970dfd1978a427dd3013b021d8 to your computer and use it in GitHub Desktop.
Save johnshearing/b0c87c970dfd1978a427dd3013b021d8 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 sixth video.

This video shows how to create signed transactions in a secure local environment and then send them to the public Ethereum blockchain without the need to run an Ethereum node or do any mining.

The biggest advantage to creating signed transactions is security. The idea is to create a signed transaction 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 can spook around your computer and find your private key.

Two methods are shown. One uses a service called INFURA and the other uses a service called BlockCypher.
We will be working with INFURA first.

Setup the Project Folder Environment

Setup is the same as in notes for video 2.
The Node dependencies are listed as follows

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

I am just using the project folder from Video 4 because dependent packages are already installed.

Set up two accounts for use on the public Ethereum blockchain AKA MainNet

For this project you will need two public/private key pairs. One key-pair will be used to send ether and the other key-pair will be used to receive the sent ether.
I made two public private key pairs using methods shown in the notes for Jordan's second video.
Here is the part about making private keys. Don't forget to require web3 and instantiate it before using the commands linked here.
And here is the part about making public keys

I hashed the phrase TunaMotorcycleWeekSpectroGotClog001
The following is the hash or private key:
0xf94bdc3158e60dd37d60986d0ccd0c74911743b46c8b61eca7f51aea49d80499
The following is the public address or public key which was determined using the private key as per the notes linked above:
0xf3131af7a791436c6787c4fc6fbc66916d1a13fe
This key-pair will be used to send some ether on the MainNet.

I did the same with the following phrase TunaMotorcycleWeekSpectroGotClog002. Notice the last character has been changed.
The following is the private key.
0xd9003665080effb22d48eba386bfc78e20311c9e91d584226e469d7d6e41e3d3
The following is the public address or public key.
0x28c67d97663f41e04c4e804d818bdd7fa4692509
This key-pair will be used to receive ether sent by the first key-pair we made.

The cool thing to understand is that Ethereum accounts are made simply by creating key-pairs and you don't even have to interact with a blockchain to create key-pairs. The important things to remember are:

  • The phrase used to create the private key must be very very difficult to guess and something that no one will ever create by chance.
  • The private key and the phrase used to create it must never be exposed to the Internet or discovered in any way.
  • You can give the public key to anyone with no fear of losing your ether.
  • Anyone can put money into any account using the public address.
  • Only the private key holder can withdraw ether from an account.
  • The blockchain is a public ledger. Anyone can see how ether gets into your account and where it goes when you send it.

Since I have exposed the private keys for the above two accounts they are not secure - anyone can remove ether from those accounts. There is a little bit of ether in there now so you can use these to practice sending ether between the accounts but please leave the ether between those two accounts so that other people can practice.

Check and see how much ether is in each account. Go to https://etherscan.io/ and paste one of your public addresses not the private keys into the search box and press Enter.
Then do the same with the other account.
Now you know how much is in each account.

If you are making your own accounts then load the one of the accounts with some ether so that you can send it to your other account. If you have purchased ether from www.coinbase.com or from some other similar service then you can use their web interface to send a little practice ether to one of your public addresses. If you have some ether left in your account after purchasing the DecypherTV videos then you can use Meta mask to send ether to one of your new accounts.

Sending Transactions Using INFURA

Go to https://infura.io/register.html to get started.
After signing up, a webpage with various personalized URLs will be displayed which provide entry points to the public Ethereum block chain and also the public Ethereum test network called Morden.
URLs to the IPFS (InterPlanetaryFileSystem) are also provide but these do not appear to be linked with your identity.
Copy the link to the Main Ethereum Network onto the clipboard.
Note that it will not be necessary to run a blockchain node with geth.exe.

Create a variable which holds the URL you just copied to the clipboard. Open your favorite command line interpreter and navigate to the folder you set up for this exercise.
Start the NodeJS console by typing node and pressing Enter.
Execute the following line of code:
var endpoint = "the_link_I_just_Copied"
The Node console will output "undefined".

Tell Node where to find the web3 library.
Execute the following line of code.
var Web3 = require("web3")

Tell Node where to find the transaction library
Execute the following line of code.
var EthTx = require("ethereumjs-tx")

Create an instance of the web3 library in Node and connect it to the Main Ethereum Network via INFURA.
Execute the following line of code.
var web3 = new Web3(new Web3.providers.HttpProvider(endpoint))

Check that web3 is instantiated.
Execute the following line of code.
web3
The Node console should output the web3 API

Create two variables to hold the public addresses for which the private keys are known. Remember we made these at the beginning of the notes. The first one will be the sender's public address and the second one will be the recipient's public address.
Execute the following lines of code.
var addr1 = "0x...in_quotes"
var addr2 = "0x...in_quotes"

Now we will define the transaction instructions.
The sender's private key is not necessary for this step but we will need it later to sign the transaction.
Execute the following block of code.

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

Now Execute the variable name rawTx to check that the transaction instructions are as desired before sending it off.
Paste the following variable name into the command line interpreter and press Enter.
rawTx
The Node console will output the transaction instruction data object which should look much like the following

> rawTx
{ nonce: '0x0',
  to: '0x28c67d97663f41e04c4e804d818bdd7fa4692509',
  gasPrice: '0x4e3b29200',
  gasLimit: '0x5208',
  value: '0x3782dace9d90000',
  data: '' }

Notice that the rawTx function found acct1 on the public block chain and returned the transaction count as the nonce.

Create a variable to hold the private key for account 1 (The sender's account)
For this we will use the first private key (the sender's private key) I created earlier.
Execute the following line of code.
var pKey1 = "f94bdc3158e60dd37d60986d0ccd0c74911743b46c8b61eca7f51aea49d80499"
Notice that the first two characters 0x have been omitted. These charters only denote that we are working with a hexadecimal number and are not part of the actual data.

Now convert the private key into the buffer format and save the result to a variable so that it can be used by the ethereumjs-tx library.
Execute the following line of code.
var pKey1x = new Buffer(pKey1, "hex")

Execute the variable name to see what's in the buffer.
Paste the following into your command line interpreter and press the Enter key.
pKey1x

Instantiate a transaction object and load it with the transaction instructions defined earlier.
Execute the following command.
var tx = new EthTx(rawTx)

Now sign the transaction with the private key.
Execute the following command.
tx.sign(pKey1x)

Take a look at what's in the tx object.
type tx at the command line and press Enter. You should see something that looks like the following

> tx
Transaction {
  raw:
   [ <Buffer >,
     <Buffer 04 e3 b2 92 00>,
     <Buffer 52 08>,
     <Buffer 28 c6 7d 97 66 3f 41 e0 4c 4e 80 4d 81 8b dd 7f a4 69 25 09>,
     <Buffer 03 78 2d ac e9 d9 00 00>,
     <Buffer >,
     <Buffer 1c>,
     <Buffer 8e f7 46 cb 92 d2 ee 58 4c cb a8 e9 96 3e 0b 8e f8 06 37 0b 4d 85 02 0a f2 d5 5d 29 d4 5c 68 56>,
     <Buffer 1e 36 6d 13 5e fb 69 ea dc 94 21 72 a3 40 01 5a fb 59 1b f3 f3 36 e1 75 26 e2 3c 77 02 fc 29 e1> ],
  _fields:
   [ 'nonce',
     'gasPrice',
     'gasLimit',
     'to',
     'value',
     'data',
     'v',
     'r',
     's' ],
  toJSON: [Function],
  serialize: [Function: serialize],
  nonce: [Getter/Setter],
  gasPrice: [Getter/Setter],
  gasLimit: [Getter/Setter],
  to: [Getter/Setter],
  value: [Getter/Setter],
  data: [Getter/Setter],
  v: [Getter/Setter],
  r: [Getter/Setter],
  s: [Getter/Setter],
  from: [Getter],
  _chainId: 0,
  _homestead: true }
>

All the information required to send the transaction is in there including your digital signature (the private key) but it is not yet encrypted and formatted to send.

Encrypt and format the signed transaction so that it can be sent to the MainNet securely over the Internet.
Execute the following command.

var serializedTx = `0x${tx.serialize().toString('hex')}`

And now let's take a look at what our transaction looks like after it has been encrypted and serialized for sending over the Internet.
Input the variable name serializedTx into the CLI and press Enter. You should see something like the following. '0xf86c808504e3b292008252089428c67d97663f41e04c4e804d818bdd7fa46925098803782dace9d90000801ca08ef746cb92d2ee584ccba8e9963e0b8ef80637 0b4d85020af2d55d29d45c6856a01e366d135efb69eadc942172a340015afb591bf3f336e17526e23c7702fc29e1'
This string can now be securely sent to the blockchain where it will be decoded with your public key in such a way as to prove that the message was signed with the correct private key (authorized by you), and that the message sent is exactly the same as the message received.

Now it's time to send the transaction to the blockchain for processing.
Execute the following command.

web3.eth.sendRawTransaction(serializedTx, (error, data) => {
   if(!error) {console.log(data)} else {console.log(error) }})

If there was no error, then the console will return a transaction hash which should look something like the following:
0x0bb599232cc836c16ca2d01a812e7942f75673adff3ef58331087bbabc9021ad
This can be used to progress of the transaction or it can be used to find information about the transaction at a anytime in the future.

If everything went well we should be able to look at the transaction on https://etherscan.io/
Go to https://etherscan.io/ and past the transaction hash into the search field.
Information will populate the screen about your transaction.

Now you can check the account balances by cutting and pasting the public addresses of an account into the same search field at https://etherscan.io/ and pressing Enter.

Don't be a bonehead: paste the public key into the search box not the private key. If you accidently send the private key over the Internet you may lose your ether to criminals. Bad people set up computers to scan network traffic to see if public keys have accidently been exposed. If your mistake has been noticed by one of these computers then your ether will be gone from your account in seconds. If you have accidently sent the private key over the Internet or exposed it in any way, then immediately move your ether to another account of which the private key is known only to you. Do this before others have a chance to take advantage of your mistake.

The blockcypher service can not only be used to send ether but it can also be used to send and interact with smart contracts.
Create a new account.
The website will return a token after registration as shown in the video.
You will need this so save it by cutting and pasting it into a file somewhere on your computer.

Download cURL

Download cURL to your computer. The cURL download can be found here
A lot of files will be downloaded but for this exercise you will only need curl.exe.
Put curl.exe in your project folder.

cURL is a command line tool that allows you to interact with Internet servers as if it were a webpage.
You can learn all you need to know about cURL at the following link.
https://curl.haxx.se/

Create secure transaction instructions as before.

At the Node console load a variable with new transaction instructions.
Paste the following command block into your Node console and press Enter.

var rawTx = {
   nonce: web3.toHex(web3.eth.getTransactionCount(addr1)),  
   to: addr2,  
   gasPrice: web3.toHex(21000000000),  
   gasLimit: web3.toHex(21000),
   value: web3.toHex(web3.toWei(.1, "ether")),
   data: ""
   }

This is the same transaction instruction as before except I am only sending .1 ether this time.

Check the transaction instructions:
Execute the following command at the Node console.
rawTx
Notice that the nonce reflects the number of outgoing transactions made by this account.

Reload the transaction variable with the new transaction instructions:
Execute the following command at the Node console.
var tx = new EthTx(rawTx)

Look at the variable tx:
Execute the following command at the Node console.
tx
You will notice the output is in the form of a buffer.

Now sign the transaction passing in the buffer which holds the private key:
Execute the following command at the Node console.
tx.sign(pKey1x)

Create an encrypted serialized transaction instruction string from the signed transaction buffer:
Execute the following command at the Node console.
tx.serialize().toString("hex")
The Node console will output a rather long encrypted serialized transaction instruction string. We will use this string to securely pass transaction instructions to an Internet connected computer:

  • Without exposing our private key
  • With certainty that the transaction was authorized by the account's private key holder
  • With certainty that the transaction will not go through if any characters of the string have been changed

Copy the Node console output to the clipboard.

Send the transaction using the BlockCypher service:

The following must be done at the operating system's command line prompt (Not the Node console).
Open your favorite command line interpreter and navigate to your project directory. Then type in the following command passing in an object named tx which contains the encrypted serialized transaction string that you copied onto the clipboard a moment ago.
Do not execute the command yet. We need to add more to it.
So far your command should look something like the following.
The encrypted serialized transaction instruction string will be different for you of course.

curl -sd '{"tx": "f86c018504e3b292008252089428c67d97663f41e04c4e804d818bdd7fa469250988016345785d8a0000801ba0572bef0e882ab210bc34de3679331c680a88c6ab67a716bcf6bbcbc75bca8210a038e8f217b20793f2999d013a44c17b78b1d2adc751f4ced091c7fffc38206db3"}'  

Take notice of the characters -sd.
The "s" tells cURL to output a minimal amount of information to console.
If you put a capital "S" in it's place than you would get very good reporting about command execution.
The "d" tells cURL that the object that follows is the data to be sent.

Append the following code to the previous command.
The token from BlockCypher (the stuff after the equal sign) will be different for you of course.
https://api.blockcypher.com/v1/eth/main/txs/push?token=63f41e04c4e804d818bdd7fa46925098
This tells cURL where to send the Data and supplies the token required by BlockCypher.com.

Now the whole command should look something like the following:
The transaction string and the token will be different for you of course.

curl -sd '{"tx": "f86c018504e3b292008252089428c67d97663f41e04c4e804d818bdd7fa469250988016345785d8a0000801ba0572bef0e882ab210bc34de3679331c680a88c6ab67a716bcf6bbcbc75bca8210a038e8f217b20793f2999d013a44c17b78b1d2adc751f4ced091c7fffc38206db3"}' https://api.blockcypher.com/v1/eth/main/txs/push?token=63f41e04c4e804d818bdd7fa46925098

If you are using a Mac or Linux then the command should run on your computer and ether will be transfered. I haven't tested it because I am using the Windows OS. But if you are using Mac or Linux make the approriate changes and execute the command.

If you are on the Windows operating system then there is more work to do.
To use cURL with the Windows OS we will need to put the json object in its own file and call it when executing the cURL command. The reason this is necessary is because the cURL command encloses the json object in single quotes and these are not recognized by the Windows command line interpreter. So putting the json object in its own file gets rid of the need to use single quotes.

For this example create a file in your project directory and name it BlockCypherJSON.txt

Now from the above command, cut everything from inside the single quotes and paste it into the file you just created. The part you want to move into the new text file is shown below (it's the transaction object). Do not include the single quotes shown above - leave the single quotes where they are for the moment. Please remember that the code below is just to give you a clear idea of what needs to be moved. The code you move will be different of course because your "signed encrypted serialized transaction instruction string" will be different than what is show.
{"tx": "f86c018504e3b292008252089428c67d97663f41e04c4e804d818bdd7fa469250988016345785d8a0000801ba0572bef0e882ab210bc34de3679331c680a88c6ab67a716bcf6bbcbc75bca8210a038e8f217b20793f2999d013a44c17b78b1d2adc751f4ced091c7fffc38206db3"}

Then replace the single quotes still in the command with the following text:

@BlockCypherJSON.txt

Now the command should look something like the following except that the characters after the equals sign will be the unique token that you got from BlockCypher.com. As you can see, you have moved the JSON object from inside your cURL command into its own file and you have added a pointer to the command so that cURL can still find the JSON object. All this was done just to get rid of the single quotes because Windows cannot work with them at the command prompt.

curl -sd @BlockCypherJSON.txt https://api.blockcypher.com/v1/eth/main/txs/push?token=63f41e04c4e804d818bdd7fa46925098

Now add a dot and a slash to the very front of the command. These characters tell command line interpreter to look in the project directory for cURL.exe.
Your command should now look something like the following. The token will be diffenrent of course.

./curl -sd @BlockCypherJSON.txt https://api.blockcypher.com/v1/eth/main/txs/push?token=63f41e04c4e804d818bdd7fa46925098

Next you will need to create a file into your project directory that will be used to establish trust between your computer and BlockCypher's server. Name the file cURL_CA.txt

Now cut and paste all the text found at the link below into the file you just created.
The text you need is found here

Finally, tell cURL where to look for this file.
Add the following option to your command:
--cacert cURL_CA.txt

Now your command should look like the following. Your token will be different of course.

./curl --cacert cURL_CA.txt -sd @BlockCypherJSON.txt https://api.blockcypher.com/v1/eth/main/txs/push?token=63f41e04c4e804d818bdd7fa46925098

If you are using the Windows OS, execute the above command after you have changed the token characters to match the token you received from BlockCypher.com.

If everything went well the OS console will output an object with lots of information about your transaction.
Go ahead and check the accounts using https://etherscan.io/ to see if the transaction went through.

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