7 min read - Posted 13 Feb 19

Ethereum 101 - Part 4 - Accounts, Transactions, and Messages

Accounts, Transactions, and Messages

The Ethereum state is made up of accounts, and the transactions among those accounts propel the network forward, ensuring network validators receive appropriate compensation for their Proof of Work computations securing the blockchain.

The blockchain is a state transition system. The “state” is the ledger of all existing Ethereum accounts, smart contracts, and ether ownership. In a “state transition function” that state is used to execute a transaction and the output of that transaction becomes the new state. As transactions are submitted to the network by externally owned accounts, they move the Ethereum blockchain to its newest state.

Quick Overview

There are two different types of accounts:

  • Externally owned accounts (acronym: EOA)
  • Contract accounts

Externally owned accounts are controlled by their private keys, while contract accounts are controlled by their contract EVM bytecode, a topic that will be discussed in another section.

Address (do not send money to this address, it may be lost):

The address is your public facing element of your account. If you are to receive Ether, you will direct that transaction to this address. The address is simply the Keccak-256 hash of the public key, which is not listed in this section.

Private Key (with this key, you have control over the above address):

Supplemental Technical Information

Mnemonic Seed Phrases & BIP39

Some decentralized apps and wallets use mnemonic phrases or JSON files for account recovery (e.g. MetaMask uses a 12 word seed phrase for account restoration). Similar as you would with private keys, mnemonic phrases and keystore files (typically a JSON file) should be duly protected.


Should someone learn your mnemonic phrase or obtain your JSON keystore file, they may be able to recover your account and gain access to your funds. For more information, please reference the knowledge bases of MetaMask (https://support.metamask.io/) and MyEtherWallet (https://myetherwallet.github.io/knowledge-base/).

Primer on Asymmetric Cryptography

Accounts are derived through complex and inherently secure asymmetric cryptography. The creation of an Ethereum account is a three step process:

  • First, a 64 character hexadecimal private key is randomly generated.
  • Second, the public key is generated by taking the 64 character hexadecimal private key and applying elliptic curve multiplication (this is an irreversible calculation).
  • Third, take the Keccak-256 hash of the newly generated public key, take the final, furthest right 40 characters of this hash, and prefix these 40 characters with ‘0x’. This is the account address.

Using our accounts’ derived asymmetric private key and address, we can begin executing transactions. The term transaction refers to a signed data package that is sent from an externally owned account. Similar to a transaction, a message call is produced by a contract, not an externally owned account. Contracts can even make message calls to other contracts. The white paper describes contracts not as objects that must be fulfilled, but instead as a block of code on the blockchain that is executed when called by an externally owned account or another contract (via a message call).

In the event we are conducting a raw transaction between two external accounts, the process is straightforward. First, we need three parameters: the account that is sending the transaction, the account that will be receiving the transaction value, and the value of the transaction. Additional parameters are required: nonce, gasLimit, and the gasPrice, though we do not need to derive these values on our own as they will be populated by the geth console.

  • nonce: this is the transaction count of the account sending the transaction (not to be confused with the Proof of Work nonce, as this is a different nonce).
  • gasLimit (STARTGAS): an upfront value paid by the externally owned account setting the maximum price paid to execute the transaction; if all gas is exhausted the transaction is reverted back to its previous state. Any unused gas is typically returned to the transaction sender.
  • gasPrice (GASPRICE): the value of each computation step (an EVM opcode) paid by the externally owned account to execute the transaction.

Sending a transaction with ethereumjs-tx

For the purposes of this document, we will be using ethereumjs-tx to execute this transaction. Installation is simple, please use the command below:

$ npm install ethereumjs-tx

Next, let’s get a geth console running and obtain some values to help us better define our transaction parameters. Let’s use the Rinkeby testnet for this exercise. You will need to obtain ether from the Rinkeby faucet @ https://faucet.rinkeby.io/.

Open up a terminal and input the following geth commands:

> geth --fast --cache=1024 --rinkeby console 2>>eth.log

Utilize a second terminal to view the geth feed:

> tail -F eth.log

Obtain our transaction nonce using the below command in our geth node:

> web3.eth.getTransactionCount(“<insert account here>”)

Now that we’ve found our transaction nonce, let’s assemble the code that will push our transaction onto the ethereum network. Understanding the transaction nonce and how it prevents double-spending on the Ethereum blockchain is important. Assume that an Account A is sending 3 ether to Account B, and Account A only has that 3 ether in its account. Account A signs and broadcasts this transaction to the network. Subsequently, while using a higher gas price, Account A then signs and broadcasts a second transaction to C in the amount of 3 ether. The higher gas price warrants the second transaction a higher queue in the pending transaction pool, effectively executing a double spend.

The nonce is what prevents this double spending from happening, as account transactions need to be sequential. In our above example, assuming the account has a nonce of 0, the first transaction will be written to the blockchain. The second transaction, even with the higher gas price, will be rejected because the nonce is +1 more than the first transaction’s nonce. The blockchain will interpret that Account A will not have enough ether to execute the second transaction, even though it was sent with a higher gas price, and will then reject that second transaction.

In our nodejs console:

> const EthTxn = require(“ethereumjs-tx”)
> const privKey = Buffer.from(“<INSERT PRIVATE KEY>”, “hex”)
> const txnParams = {nonce: “0x00”, gasPrice: “0x2540be400”, gasLimit: “0x222e0”, to: “<INSERT DESTINATION ADDRESS HERE>”, value: “0x2fe01dba2bb1dffe”, data: “0x00”, }
> const tx = new EthTxn(txnParams)
> tx.sign(privKey)
> const serializedTx = tx.serialize()
> const rawTxn = “0x” + serializedTx.toString(“hex”);
> console.log(rawTxn)
// this will output a long transaction string

The above console.log(rawTxn) command will return a raw transaction string. Input this raw transaction string into your geth console using the below command: > eth.sendRawTransaction(“0xf86d018520540be400839752e094a18d70840b9bc475ba15f4f6a98d 2967744fe4c1882fe01dba2bb1dffe001ba0984e42f70a04d17e56b965423ae83527ee701cfb56e2b701b8b46e9c94461303a01ffd3efc1bcc7eb5f85fa1929cb2ca52706a59f0c48febe488c3c56aee5d164e”)

In your second terminal you will find output similar to the below: INFO [XX-XX|XX:XX:XX] Submitted transaction ...

To summarize, the above tutorial explains how to send transactions from an externally owned account. It’s important to understand that contracts do not initiate transactions. Contracts are able to send messages to other contracts, but to do this, the contract must receive a message from an externally owned account.

Contract messages are different, they do not have a gas limit, as the gas costs set by the externally owned account initiating the transaction must be sufficient enough to carry the whole execution through to completion. In the event a message execution runs out of gas, then that particular message will halt and revert back to its previous state, unwinding all prior computational steps effectively restoring its previous state. This is an unsuccessful transaction.

Since we sent the above transaction on the Rinkeby testnet, you could simply use Etherscan to view your address, the transactions you’re sending and receiving at that address, as well as the externally owned accounts and contracts that received your test ether. Many decentralized apps reference Etherscan to obtain a quick glimpse of your activity on the blockchain. Take a moment to review: https://etherscan.io

Additional Web3 Libraries

Web3js - JavaScript

Web3py - Python

Web3j - Java

Additional reading:

Created with Sketch.Content is"CC-BY-SA 4.0" licensed
Article On-chain
Article Author

Wil Barnes

Software Engineer




Related Articles
Sending Ethereum Transactions with Rust

This tutorial walks you through the code required to send an Ethereum transaction within a Rust application. Prerequisites We assume that you already have a Rust IDE available, and have a reasonable knowledge of Rust programming. We also assumes some basic knowledge of Ethereum and do not cover concepts such as the contents of an Ethereum transaction. For more on any of these subjects, read the following: Getting started with Rust Ethereum 101 Libraries Used This tutorial uses the MIT licensed r

Web3j Transaction Managers

A Transaction Manager in Web3j is an abstraction that controls how transactions are signed and broadcast to the Ethereum network, via a connected client. You can pass an implementation to a smart contract wrapper when deploying or loading a contract, or you can use it to directly send transactions in a more manual way. There are multiple different Transaction Manager implementations included, all extending the TransactionManager abstract class. Each extending class must implement the abstract se