(This is a first draft of the start of a paper about what E. is.)
In this article I’m going to gloss over many of the details of the inner workings of Etherium and mostly skip to the practicality of creating a functional application utilizing the platform. If you are interested in more details you can read the Etherium yellow paper here: https://ethereum.github.io/yellowpaper/paper.pdf or take a look at this great article: https://medium.com/@preethikasireddy/how-does-ethereum-work-anyway-22d1df506369
Etherium is essentially a transaction-based state machine with each transaction and change of state stored on a blockchain. Etherium differs from Bitcoin and many other blockchains in that it processes code in a turing complete language via the Etherium Virtual Machine. What allows this to happen is that Etherium stores two different types of accounts, contract accounts and externally owned accounts. Externally owned accounts are controlled via a private key held by the owner of the account, with which they sign all transactions. Externally owned accounts can send “messages” which are essentially exchanges of value to each other or to contract accounts. Messages to contract accounts can trigger code that is capable of doing… just about anything and can cascade through and change the state of any number of other accounts. Each contract account contains both EVM code and local storage. Everything on the Etherium blockchain is hashed and stored in Merkle Patricia trees, including both the local storage in each contract account and the mapping of state, transactions and receipts that make up the ecosystem. What this means practically is that it is easy to validate the immutability of the stored data as any change to a leaf of either the local storage or the state of the blockchain will percolate up the tree and alter the hashes of all past data.
Like the Bitcoin blockchain, all blocks are validated by miners who receive a fee for block validation. While the Bitcoin blockchain has transaction times of 10 minutes or so, the difficulty of mining Etherium blocks are calculated to maintain a transaction of speed 15 seconds… which makes regular interaction with contracts a much faster… though still rather slow... process. Unlike bitcoin, which is just a digital ledger for value transactions, every full node on the Etherium blockchain has to run all the executable code whenever code execution is triggered within a contract… and store all the resulting changes in state and storage. To keep this manageable, there’s a price associated with every transaction called gas. Gas is measured in Ether and every transaction is sent with a corresponding amount of gas - that is the amount the sender of the transaction is willing to pay for it to be recorded in the blockchain. If the transaction completes before the limit is reached, the remaining gas is refunded, however if the transaction runs out of gas before completion, it is reverted to the previous state and no gas is refunded. Things that increase gas costs include any type of computation or data storage, as detailed in the EVM opcodes here: (https://github.com/trailofbits/evm-opcodes)[https://github.com/trailofbits/evm-opcodes]. For instance it would cost 0.09 ETH or $26.55 to add two numbers together 1 million times. This can put some serious design constraints on the logic you write a smart contract!
With that in mind here’s an example contract I got from a lesson at https://www.udemy.com/ethereum-and-solidity-the-complete-developers-guide/. The code is written in solidity - a high level language that reminds me of a cross between java and javascript with some built-in functionality around handling contracts that compiles down to EVM bytecode. In this contract we are setting up a lottery so that any number of people can enter in to the lottery for an amount of ether and only the initiator of the lottery contract can call the pick-winner() function which "randomly" picks a winner and all the ether held in the contract account is sent to them. Some things to note:
pragma solidity ^0.4.17;
contract Lottery {
address public manager;
address[] public players;
function Lottery() public{
manager = msg.sender;
}
function enter() public payable{
require(msg.value > .01 ether);
players.push(msg.sender);
}
function random() private view returns (uint){
return uint(keccak256(block.difficulty, now, players));
}
function pickWinner() public restricted{
uint index = random() % players.length;
players[index].transfer(this.balance);
players = new address[](0);
}
modifier restricted(){
require(msg.sender == manager);
_;
}
function getPlayers() public view returns (address[]) {
return players;
}
}