The basic principles of Ethereum include: Ethereum account, Ethereum virtual machine, key file, transaction, Gas, Ethereum block, Ethereum
1. Basic principles of Ethereum
1.1 Introduction to Ethereum
Ethereum is an open source public blockchain platform with smart contract functions, which provides a virtual machine to process peer-to-peer contracts. The concept of Ethereum was first proposed by Vitalik Buterin from 2013 to 2014, and began to develop through ICO crowdfunding in 2014
The essence of Ethereum is a state machine (read input and output)
Compared with Bitcoin's 10 minutes to generate a block, it takes about 15s for each block to be generated by Ethereum. Ethereum regards 30,000 blocks as an epoch, and each epoch takes 125 hours. This is also achieved through the difficulty adjustment algorithm. Achieved
GHOST protocol
The time interval for the generation of Ethereum blocks is 15s. During this period, if different nodes have packaged the blocks, it is impossible to determine which node’s block should be included at this time, and then let the nodes compete who will pack the next block first. Whoever digs out the block first wins, but by analogy, the node with the strongest computing power will control the entire chain, because in a longer period of time, it will definitely be able to generate a longer chain, and the packaging of nodes with small computing power Blocks will not be adopted by nodes with strong computing power
In order to solve the above problems, Ethereum uses the GHOST protocol
1. Each block must have a parent block and 0 or more uncle blocks
2. The uncle block must be the direct block of the k generation ancestor of the current block, 2 <=k <=7
3. The uncle block cannot be the ancestor of the current block
4. The uncle block must have a legal block header, but it may not be verified, and it is not even a legal block
5. Uncle blocks cannot be included repeatedly
Reward for mining an uncle block
(uncle.numer + 8 - header.number)/8*blockReward
Mining out an uncle block can get at least 1/4*blockReward
Rewards for referencing n uncle blocks
n*1/32*blockReward
You can quote up to 2, that is to say, you can get 1/16 of the reward
Reward for packing a valid block
Gas费用 + 引用n个叔块的奖励 + 静态奖励
Summary: The GHOST protocol essentially urges the nodes that have mined uncle blocks to hand over the mined nodes as soon as possible for the main chain nodes to reference, and then dig the latest block, so that driven by the maximization of benefits, the nodes will try their best to Package blocks on a chain
1.2 Ethereum account
Ethereum has two types of accounts: contract accounts and external accounts
The function of the external account is the same as the account model of Bitcoin: sending transactions, checking balances, etc., but the mechanism is different: specifically: private key-public key-address-taking the last 20 digits
Contract account: The contract account is generated when the contract is deployed and is used to charge gas fees. The caller needs to pay a certain gas fee to execute. These transaction fees will be rewarded to the node that generated the block
Account Status
type Account struct {
Nonce uint64
Balance *big.Int
Root []byte
CodeHash []byte
}
nonce: represents the transaction quantity of the external account, and represents the contract number created by the contract account
balance: balance (unit wei)
storageRoot: the hash value of the root node of the Merkle Partricia tree
codeHash: The external account is the hash value of the empty string, and the contract account is the hash value of the EVM code (the hash value of the contract code)
Each block has a header, which contains three trees, state tree, transaction tree, receipt tree
Node type: full node and light node. The amount of data downloaded from the full node is relatively large. As of now, the block height is 14628886, and the light node only contains the block header
1.3 Gas and fees
Gas is required to be paid for various operations in Ethereum, such as storing data, creating contracts, and performing hash calculations, etc.
gas = gasPrice * gasLimit: The highest gas fee that the operation initiator is willing to pay for an operation
GasPrice is usually equal to 1gwei = one hundred millionth of an ETH (1ETH = one billionth of a billionth of wei). When the computing power in the network decreases, the gasPrice will rise to attract more nodes to participate in block packaging. In addition, gasPrice will directly affect the transaction speed
gasLimit: the upper limit of gas consumption in an operation
This mechanism is mainly to prevent gas waste caused by unknown errors, and it is necessary to reduce losses as much as possible. For example, during a contract call, an unknown error causes a loop, causing the contract to be executed all the time, which will consume a lot of gas. Setting gasLimit can reduce this loss
The gas requirements for common operations in Ethereum
Basic transaction fee: 500gas
Create a contract: 53000gas
Transaction per byte: 5gas
The core of the fee mechanism is to maintain the security and prosperity of the network
1.4 Transactions and Messages
Two transaction types: transactions and messages
The transaction is initiated by an external account and sends a signed data packet storing a message to another account (here it can be understood as a transfer)
The message is initiated by the internal contract, which is essentially a transaction
Both transactions and messages contain:
nonce: The nonce here is different from the nonce in the account (the number of transactions completed in the account). It is an accumulative integer, which can be specified optionally. It needs to be greater than the nonce value in the account, which will affect the transaction being packaged into the block time. For example, if the nonce in the account is 2, when sending a transaction, specify it as 4, then the transaction will not be packed into the block immediately, but will be put into the transaction pool and wait until the missing nonce is submitted to the transaction pool middle. During the actual transfer, the previous one can be overwritten by submitting a transaction with the same nonce
gasPrice: general wallets will calculate an average
gasLimit:
to: payee address
value: transfer amount
v, r, s: data signature, verify the legitimacy of the transaction
init: the EVM code fragment that initializes the new contract account
data : For external account transactions, it is optional. For contract creation, it is the compiled contract bytecode; for contract method invocation, it is the contract method signature and parameter encoding
Contracts can call and execute each other without Gas fees
valid transaction
Transactions must be properly formatted RLP
valid signature
The transaction number is valid
The gas limit is greater than or equal to the intrinsic gas used by the transaction
1.5 blocks
Contains block headers, transaction information, and other information
type Block struct {
header *Header
uncles []*Header
transactions Transactions
// caches
hash atomic.Value
size atomic.Value
// Td is used by package core to store the total difficulty
// of the chain up to and including the block.
td *big.Int
// These fields are used by package eth to track
// inter-peer block relay.
ReceivedAt time.Time
ReceivedFrom interface{}
}
Block header, which contains three trees: state tree, transaction tree and receipt tree
// Header represents a block header in the Ethereum blockchain.
type Header struct {
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase common.Address `json:"miner" gencodec:"required"`
Root common.Hash `json:"stateRoot" gencodec:"required"`
TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *big.Int `json:"difficulty" gencodec:"required"`
Number *big.Int `json:"number" gencodec:"required"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
Time uint64 `json:"timestamp" gencodec:"required"`
Extra []byte `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
// BaseFee was added by EIP-1559 and is ignored in legacy headers.
BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
/*
TODO (MariusVanDerWijden) Add this field once needed
// Random was added during the merge and contains the BeaconState randomness
Random common.Hash `json:"random" rlp:"optional"`
*/
}
log
Logs can track various transactions and information
Contracts can display generated logs by defining events
Log entities contain:
Logger account address
Some subjects of the various events representing the execution of this transaction and any data related to those events
Logs are saved in bloom filters, which can efficiently save endless log data
transaction receipt
Including: block number, block hash, transaction hash, gas used in the current transaction, cumulative gas used in the block after the execution of the current transaction, current transaction log
block difficulty
nonce <= 2 to the 256th power / block difficulty
Block Difficulty Algorithm
/*
Algorithm
block_diff = pdiff + pdiff / 2048 * (1 if time - ptime < 13 else -1) + int(2^((num // 100000) - 2))
Where:
- pdiff = parent.difficulty
- ptime = parent.time
- time = block.timestamp
- num = block.number
*/
1.6 Execution Mode
EVM : Ether Virtual Machine
is a Turing-complete virtual machine
stack-based architecture
The size of each stack top is 256 bits, and the stack has a maximum size of 1024 bits
have a memory
There is a dedicated language: "EVM bytecode"
1.7 Ethereum network
For distributed DApps, the network model is P2P. Ethereum is also a distributed system, which uses a distributed hash table topology, and the specific implementation is a Kademlia-like algorithm
Data interaction is required between nodes
KAD Algorithm and Node Discovery
The node discovery protocol is defined in Ethereum, and nodes use this protocol standard to discover each other
KAD algorithm
distance(A,B) = keccak256(NODEIDA) XOR keccak256(NODEIDB)
Each node maintains a routing table according to the distance, and 256 buckets are maintained in the routing table, and each bucket stores k Nodes (k=16, a maximum of 16 nodes can be stored in the specified distance range, which can increase the overall network stability), each Node uses NODEID as a unique identifier
type Node struct {//节点的类似实现
NODEID int
IP string
Port string
}
The formula between any node B and the current node A
distance(A,B) = keccak256(NODEIDA) XOR keccak256(NODEIDB)
The distance interval in the routing table maintained by the current node:
[2 ^ i, 2 ^(i+1))
Note: It is a left-open right-close interval
[ bucket0 ] : [1]
[ bucket1 ] :[2,3]
[ bucket2 ] : [4,5,6,7]
[ bucket i ] : [2^i : 2 ^ (i+1))
[ bucket i+1 ] : [...]
[ bucket ... ] : [...]
[ bucket255 ] : [2^255: 2^256)
How to initialize the routing table when the node starts. Ethereum includes some nodes in the source code. When the node starts, it will automatically synchronize the information of these nodes to complete its own routing table construction.
1.8 Ethash Algorithm
The packaging of Ethereum blocks also uses the proof-of-work mechanism like Bitcoin, but the process is different. The approximate pseudo-code process is as follows
Bitcoin: hash(nonce + preBlockHash + ...) < target
Ethereum: hash (nonce + preBlockHash + DAG... ) < target
Explanation: Ethereum uses the nonce, the hash of the previous block and the data in the dataset when calculating the hash value that satisfies the conditions
datasset is actually a DAG, and DAG data is generated every 3000 blocks, and only depends on the block number
DAG generation process: blockNumber -> seedHash -> 16MB cache -> 1GB DAG
Specific process:
A seedHash is 64 bytes, 16MB = 16777216byte / 64byte = 262144, that is to say, there are 16777216 bytes in a cache (262144 segments of 64 bytes of data, the latter segment is the hash value of the previous segment)
DAG is generated by the cache: specifically, it traverses the cache from the beginning to the end, and performs fnvHash256 on each byte and then hashes it again to get 64 bytes
And fill it into the DAG, the whole process needs to be executed 16777216 * 256 times, 16777216 * 64 = 1GB
Note: The above DAG is the initial state, and the DAG is generated every 3000 blocks, and it will become larger as time goes by
The role of DAG: to limit the impact of specialized machines packaging blocks on the network. Because every time a block is packed, it needs to loop 64 times to get 64*128 bytes of data from DAG, and the speed of getting it depends on the bandwidth of the graphics card. So the final packaging speed depends on the computing power and bandwidth