├── .gitignore
├── ethereum
├── why-use-golang-to-build-a-blockchain.md
├── ethereum-code-structure.md
├── ethereum-should-do-something-new.md
├── erc1155-token.md
├── dapp.md
├── remix.md
├── metamask.md
├── truffle.md
├── geth.md
├── smart-contracrt-best-practice.md
├── create-an-account.md
├── ethereum-trie.md
├── pos.md
├── why-we-want-a-new-blockchain.md
├── private-key-secp256k1.md
├── cross-chain.md
├── gas-eip-1559.md
├── smart-contracrt.md
├── erc20-token.md
├── mining-start.md
├── transaction.md
├── zero-knowledge-proof.md
├── evm.md
├── mining-chainconfig.md
├── ethereum-account-state.md
├── ethereum-block-and-network.md
├── erc721-token.md
└── solidity.md
├── pictures
├── fee1.png
├── fee2.png
├── trie.png
├── chains.png
├── commit.png
├── merkle.png
├── state.webp
├── Patricia.png
├── miner-uml.png
├── evm_process.jpg
├── miner-loop.png
├── tree_change.png
├── contract-demo.png
├── mining-process.png
└── evm_code_executed.png
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | *.xml
3 | *.DS_Store
4 |
--------------------------------------------------------------------------------
/ethereum/why-use-golang-to-build-a-blockchain.md:
--------------------------------------------------------------------------------
1 | Fixme
--------------------------------------------------------------------------------
/ethereum/ethereum-code-structure.md:
--------------------------------------------------------------------------------
1 | # Ethereum Code Structure
2 |
3 | Fixme
4 |
--------------------------------------------------------------------------------
/pictures/fee1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/fee1.png
--------------------------------------------------------------------------------
/pictures/fee2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/fee2.png
--------------------------------------------------------------------------------
/pictures/trie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/trie.png
--------------------------------------------------------------------------------
/pictures/chains.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/chains.png
--------------------------------------------------------------------------------
/pictures/commit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/commit.png
--------------------------------------------------------------------------------
/pictures/merkle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/merkle.png
--------------------------------------------------------------------------------
/pictures/state.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/state.webp
--------------------------------------------------------------------------------
/ethereum/ethereum-should-do-something-new.md:
--------------------------------------------------------------------------------
1 | # 01. Why Use GoLang to Build a Blockchain?
2 |
3 | Fixme
4 |
--------------------------------------------------------------------------------
/pictures/Patricia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/Patricia.png
--------------------------------------------------------------------------------
/pictures/miner-uml.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/miner-uml.png
--------------------------------------------------------------------------------
/pictures/evm_process.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/evm_process.jpg
--------------------------------------------------------------------------------
/pictures/miner-loop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/miner-loop.png
--------------------------------------------------------------------------------
/pictures/tree_change.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/tree_change.png
--------------------------------------------------------------------------------
/pictures/contract-demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/contract-demo.png
--------------------------------------------------------------------------------
/pictures/mining-process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/mining-process.png
--------------------------------------------------------------------------------
/pictures/evm_code_executed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiwensangsang/ethereum-core/HEAD/pictures/evm_code_executed.png
--------------------------------------------------------------------------------
/ethereum/erc1155-token.md:
--------------------------------------------------------------------------------
1 | # ERC-1155
2 |
3 | This is a standard that mixes ERC-20 and ERC-1155.
4 | It solves the difficulty of sending NFT in batches, and claims that it has great prospects in the blockchain game industry.
5 | There are currently no prospects.
--------------------------------------------------------------------------------
/ethereum/dapp.md:
--------------------------------------------------------------------------------
1 | # DApp
2 |
3 | - Can you describe a decentralized application?
4 | - A decentralized application, or DApp, is an application that runs on a decentralized network such as a blockchain. Unlike traditional applications that rely on a centralized server or authority, DApps operate on a peer-to-peer network of computers, where each participant has an equal say in the decision-making process. DApps are typically open-source and transparent, meaning that anyone can view the code and audit the application's behavior. DApps can be used for a variety of purposes, including finance, gaming, social media, and more.
5 | - Are there any Popular Platforms for Building Blockchain Applications?
6 | - No.
7 | - The diffs betweens DApp and smart contracts?
8 | - Smart contracts are backend services of DApp.
--------------------------------------------------------------------------------
/ethereum/remix.md:
--------------------------------------------------------------------------------
1 | # Remix
2 |
3 | Remix is a web-based integrated development environment (IDE) that helps developers write, test and deploy smart contracts. A smart contract is a self-executing computer program on the Ethereum platform that manages digital assets and data.
4 |
5 | Remix provides a visual interface and various development tools so that developers can more easily write, debug and test smart contracts. One particularly useful feature is Remix's Solidity editor, which provides features such as basic syntax highlighting and code formatting for smart contract writing.
6 |
7 | In addition, Remix also provides a connection to the Ethereum network and can interact with Ethereum nodes. By connecting to an Ethereum node, developers can test the function and performance of the contract, and perform necessary tests and verifications before deploying the contract.
8 |
9 | In Remix, various Ethereum nodes can be connected, such as local nodes, test network nodes, and main network nodes. These nodes can provide different network environments and testing options to help developers test different aspects and scenarios of contracts. At the same time, Remix also provides various plug-ins and extensions to enhance its functions and experience.
--------------------------------------------------------------------------------
/ethereum/metamask.md:
--------------------------------------------------------------------------------
1 | # Metamask
2 |
3 | Metamask is a popular cryptocurrency wallet and browser extension that allows users to interact with the Ethereum blockchain. It is available as a browser extension for Google Chrome, Firefox, Brave, and Microsoft Edge, as well as a mobile app for iOS and Android devices.
4 |
5 | Metamask connects to the Ethereum network through a variety of nodes, including Infura, which is a third-party service that provides access to the Ethereum network, as well as other public and private nodes.
6 |
7 | Compared to traditional Ethereum wallets, Metamask does not support certain features such as:
8 |
9 | 1. Storing tokens from other blockchains: Metamask is primarily designed for interacting with the Ethereum blockchain and does not support storing tokens from other blockchains.
10 | 2. Hardware wallet integration: While Metamask allows users to connect to a hardware wallet, it does not fully support hardware wallet integration like some other wallets do.
11 | 3. Advanced smart contract functionality: Metamask is primarily focused on providing a user-friendly interface for interacting with the Ethereum network, and as such, it does not support some of the more advanced smart contract features that more technical users may require.
12 |
13 | Despite these limitations, Metamask is a powerful and user-friendly tool for interacting with the Ethereum blockchain, and it has become a popular choice for both novice and experienced cryptocurrency users.
--------------------------------------------------------------------------------
/ethereum/truffle.md:
--------------------------------------------------------------------------------
1 | # Truffle
2 |
3 | Truffle is an open source framework for Ethereum blockchain development that provides a set of tools and conventions that make the development, testing, and deployment of Ethereum smart contracts easier and more efficient.
4 |
5 | The main purpose of Truffle is to speed up the development process of Ethereum smart contracts. It provides many development tools, such as contract compiler, interactive console, automated testing framework, deployment manager, etc., which can help developers quickly write, test and deploy smart contracts. In addition, Truffle also provides some convenient development conventions, such as contract file structure, best practices for writing contracts, etc. These conventions allow developers to understand and write contracts more quickly.
6 |
7 | The benefits of using Truffle include:
8 |
9 | Accelerate the development of smart contracts: Truffle provides many development tools and conventions that allow developers to write, test and deploy smart contracts more quickly.
10 |
11 | Improve development efficiency: Truffle's automated testing framework can help developers quickly test contracts and find problems in time, thereby improving development efficiency.
12 |
13 | Improve contract quality: Best practices for using Truffle can help developers write better contract code and reduce potential security vulnerabilities and bugs.
14 |
15 | Integration with other tools and platforms: Truffle can be integrated with other development tools and platforms (such as Ganache, Infura, etc.) to better support the developer's workflow.
16 |
17 | In short, Truffle is a powerful Ethereum development framework that can help developers develop smart contracts faster and more efficiently while improving the quality and security of contracts.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ethereum Core
2 | This project will give a detailed introduction to the technical history, working principles, development trends, and security discussions of Ethereum. It will also attempt to build a minimal blockchain project based on Ethereum.
3 |
4 |
5 |
6 | ### Ethereum: new blcokchain
7 |
8 | 0. [Why We Want a New Blockchain?](./ethereum/why-we-want-a-new-blockchain.md)
9 | 1. [Ethereum Trie](./ethereum/ethereum-trie.md)
10 | 2. [Ethereum Account and State](./ethereum/ethereum-account-state.md)
11 | 3. [Ethereum Block and Network](./ethereum/ethereum-block-and-network.md)
12 | 4. [Mining: ChainConfig](./ethereum/mining-chainconfig.md)
13 | 5. [Mining: Start](./ethereum/mining-start.md)
14 | 6. [PoS](./ethereum/pos.md)
15 | 7. [Zero Knowledge Proof and zk-SNARK](./ethereum/zero-knowledge-proof.md)
16 | 8. [Cross Chain](./ethereum/cross-chain.md)
17 |
18 |
19 |
20 | ### Account and Transaction
21 |
22 | 1. [Create an Account](./ethereum/create-an-account.md)
23 | 2. [Private Key: secp256k1](./ethereum/private-key-secp256k1.md)
24 | 4. [Transaction with ECDSA](./ethereum/transaction.md)
25 | 6. [Gas and EIP-1559](./ethereum/gas-eip-1559.md)
26 |
27 |
28 |
29 | ### Smart Contract
30 |
31 | 1. [What is the Importance of EVM in Ethereum](./ethereum/evm.md)
32 | 2. [What is a Smart Contract?](./ethereum/smart-contracrt.md)
33 | 3. [Solidity](./ethereum/solidity.md)
34 | 4. [Tether:Create an ERC-20 Token](./ethereum/erc20-token.md)
35 | 5. [BoredApeYachtClub:Create an ERC-721 Token](./ethereum/erc721-token.md)
36 | 6. [ERC-1155 Token](./ethereum/erc1155-token.md)
37 | 7. [Smart Contract Best Practice](./ethereum/smart-contracrt-best-practice.md)
38 | 8. [DApp](./ethereum/dapp.md)
39 |
40 |
41 |
42 | ### Security
43 |
44 | 1. [How to Protect a Smart Contract?](ethereum/how-to-protect-smart-contract.md)
45 | 1. [How to Attack a Smart Contract?](ethereum/how-to-attack.md)
46 |
47 |
48 |
49 |
50 | ### Tools
51 |
52 | 1. [Geth](./ethereum/geth.md)
53 | 2. [Metamask](./ethereum/metamask.md)
54 | 3. [Truffle](./ethereum/truffle.md)
55 | 4. [Remix](./ethereum/remix.md)
56 |
--------------------------------------------------------------------------------
/ethereum/geth.md:
--------------------------------------------------------------------------------
1 | # Geth
2 |
3 | - What is Geth?
4 |
5 | - Geth is an Ethereum client implemented in the Go programming language that allows users to interact with the Ethereum network. It provides a command-line interface for running a full node that can verify transactions, execute smart contracts, and participate in the consensus process.
6 |
7 | - What RPCs can you use to connect to Geth clients over the network?
8 |
9 | - Geth supports several Remote Procedure Call (RPC) APIs that allow external applications to communicate with a Geth client over the network. Some of the most commonly used RPCs include:
10 |
11 | - eth_call: Executes a message call transaction on the Ethereum network.
12 |
13 | - eth_sendTransaction: Sends a transaction to the network for execution.
14 |
15 | - eth_getBalance: Returns the balance of an Ethereum account.
16 |
17 | - eth_blockNumber: Returns the number of the most recent block.
18 |
19 | - What is Geth's "fast" sync, and why is it faster?
20 |
21 | - Geth's "fast" sync is a synchronization mode that allows new nodes to quickly synchronize with the Ethereum network. In fast sync mode, instead of downloading and processing every block from the genesis block, Geth downloads only the block headers and uses them to create a snapshot of the state of the network at a recent block. This allows new nodes to catch up to the current block more quickly.
22 |
23 | - How to connect two Geth clients using IPC-RPC?
24 |
25 | - To connect two Geth clients using IPC-RPC, you can specify the IPC file path using the "--ipcpath" option when starting each client. For example:
26 |
27 | - Geth client 1: geth --ipcpath /path/to/geth1.ipc
28 |
29 | - Geth client 2: geth --ipcpath /path/to/geth2.ipc
30 |
31 | - Where are accounts stored in the Geth client?
32 |
33 | - Accounts in the Geth client are stored in the keystore directory, which is typically located in the user's home directory under ".ethereum/keystore". Each account is represented by a file in the keystore directory that contains the account's private key.
34 |
35 | - How to use Geth to initiate a transaction to an account?
36 |
37 | - To initiate a transaction to an account using Geth, you can use the "eth_sendTransaction" RPC. The RPC takes a JSON object as an argument, which includes the sender's address, the recipient's address, the amount to send, and other transaction parameters. For example:
38 | - eth_sendTransaction({from: "0x123...", to: "0x456...", value: "1000000000000000000"})
39 |
40 | - This would send 1 ETH from the account at address "0x123..." to the account at address "0x456...".
41 |
42 | - Can the Geth client be used for mining?
43 |
44 | - Yes, the Geth client can be used for mining Ethereum. Geth includes a built-in miner that allows users to mine Ether and participate in the consensus process. To start mining with Geth, you can use the "miner.start" RPC. For example: miner.start(). This would start the miner and begin searching for new blocks to mine.
--------------------------------------------------------------------------------
/ethereum/smart-contracrt-best-practice.md:
--------------------------------------------------------------------------------
1 | # Smart Contract Best Practice
2 |
3 | ### Best Practice
4 |
5 | - If I have a huge project, do I need to keep all related smart contracts in one file?
6 | - No, you don't need to keep all related smart contracts in one file. You can put them in separate files and then use the Solidity import statement to include them in the main contract.
7 | - Can I only import local files in smart contract?
8 | - Yes
9 | - What is an ABI?
10 | - ABI (Application Binary Interface) refers to the specification of the functions and parameters required to interact with a smart contract.
11 | - Is it free to check the status of the smart contract?
12 | - Yes
13 | - How to set the Ether balance limit of the smart contract, what will happen if you send excess Ether to the smart contract with balance limit?
14 | - You can use the payable function and require statement to set the Ether balance limit of a smart contract. If you send excess Ether to a smart contract with a balance limit, the excess Ether will be rejected and returned to the sender's account.
15 | - How to set the value of msg.val in the smart contract account?
16 | - msg.value is a global variable that stores the amount of Ether carried by the current transaction. You can use the payable function and require statement to set the value of msg.value to any value you want.
17 | - Will the trader get a refund if the cost of executing the smart contract is less than the gas he paid?
18 | - It depends on the specific smart contract and the platform it is deployed on. Some smart contracts may have a refund mechanism built-in, while others may not. In general, if the cost of executing the smart contract is less than the gas paid by the trader, the excess gas will be lost and not refunded.
19 | - In what ways can two smart contracts interact?
20 | - Two smart contracts can interact with each other in various ways, such as through function calls, events, and messaging. Function calls allow one smart contract to invoke a function on another smart contract, passing in parameters and receiving return values. Events allow smart contracts to emit and listen for events, enabling them to communicate with each other and react to specific conditions. Messaging is a more complex form of interaction that involves sending and receiving messages between smart contracts, allowing for more sophisticated forms of communication and coordination.
21 |
22 |
23 |
24 | ### Verification
25 |
26 | What are the steps involved in smart contract verification?
27 |
28 | 1. Normalized Smart Contracts: Transform smart contracts into a mathematical model or specification so that their correctness can be more easily verified.
29 |
30 | 2. Static Analysis: Perform static analysis on the contract code to identify possible vulnerabilities and errors in the code.
31 |
32 | 3. Dynamic testing: Dynamic testing of the contract to ensure that the contract can be executed as expected in actual execution.
33 |
34 | 4. Formal Verification: Smart contracts are verified using formal methods to prove that they conform to the specification.
35 |
36 | 5. Manual review: A professional audit team will manually review the contract to find other possible loopholes and security issues.
37 |
38 |
39 |
40 | ### Deploy
41 |
42 | - How to deploy a file with multi smart contracts?
43 | - When attempting to deploy a file with multiple smart contracts, each smart contract will need to be compiled and deployed separately. This is because each smart contract has its own address and bytecode and needs to be deployed independently of other smart contracts.
44 | - If you're using the Ethereum Virtual Machine (EVM), you can use development tools like Truffle to compile and deploy smart contracts. Truffle can help you automate this process and ensure that each contract is deployed correctly.
45 | - When deploying multiple smart contracts, you need to ensure that the communication between the smart contracts is correct. This can be achieved by defining interfaces and calling functions between smart contracts. You also need to ensure that each smart contract has access to the other contracts it needs.
46 | - In summary, deploying a file with multiple smart contracts requires separate compilation and deployment, and ensuring correct communication and dependencies between smart contracts.
47 |
48 |
49 |
50 | ### Test
51 |
52 | To be done.
--------------------------------------------------------------------------------
/ethereum/create-an-account.md:
--------------------------------------------------------------------------------
1 | # Create an Account
2 |
3 | There are two types of accounts in Ethereum,
4 |
5 | 1. Externally Owned Account (EOA)
6 | 2. Contract Account.
7 |
8 | An EOA is a regular account controlled by a private key. In Ethereum, EOAs manage their assets and transactions through their private keys. EOAs send Ether or call contracts by signing transactions with their private keys and then broadcasting them to the Ethereum network.
9 |
10 | A Contract Account is an account managed by contract code, also known as a smart contract. It contains programmable code and persistent storage space that can be invoked and executed by other accounts. Contract accounts can receive Ether and other tokens and process them according to predetermined logic.
11 |
12 | The main difference between Contract Accounts and EOAs is that Contract Accounts can implement more complex logic through code and can enable automation of transactions, smart contracts, decentralized applications, and other features. Additionally, Contract Accounts have their own address and private key, but the private key is managed by the contract code rather than an individual.
13 |
14 |
15 |
16 | ```go
17 | // Account is the Ethereum consensus representation of accounts.
18 | // These objects are stored in the main account trie.
19 | type Account struct {
20 | Nonce uint64
21 | Balance *big.Int
22 | Root common.Hash // merkle root of the storage trie
23 | CodeHash []byte
24 | }
25 | ```
26 |
27 |
28 |
29 | Nonce: If it is an EOA account, it indicates the serial number of the sending transaction; if it is a CA account, Nonce indicates the serial number of the contract creation
30 |
31 | Balance: Indicates the balance of the account, the account balance corresponding to the account address
32 |
33 | Root: store the root of the merkle tree, if it is an EOA account root is nil
34 |
35 | CodeHash: EVM Code bound to the account, if it is EOA, CodeHash is nil
36 |
37 |
38 |
39 | ### Create
40 |
41 | Use this to create,
42 |
43 | ```go
44 | personal.newAccount()
45 |
46 | func (ks *KeyStore) NewAccount(passphrase string) (accounts.Account, error) {
47 | _, account, err := storeNewKey(ks.storage, crand.Reader, passphrase)
48 | if err != nil {
49 | return accounts.Account{}, err
50 | }
51 | // Add the account to the cache immediately rather
52 | // than waiting for file system notifications to pick it up.
53 | ks.cache.add(account)
54 | ks.refreshWallets()
55 | return account, nil
56 | }
57 |
58 | // Get PubKey, PrevKey and address
59 | func storeNewKey(ks keyStore, rand io.Reader, auth string) (*Key, accounts.Account, error) {
60 | key, err := newKey(rand)
61 | if err != nil {
62 | return nil, accounts.Account{}, err
63 | }
64 | a := accounts.Account{Address: key.Address, URL: accounts.URL{Scheme: KeyStoreScheme, Path: ks.JoinPath(keyFileName(key.Address))}}
65 | if err := ks.StoreKey(a.URL.Path, key, auth); err != nil {
66 | zeroKey(key.PrivateKey)
67 | return nil, a, err
68 | }
69 | return key, a, err
70 | }
71 |
72 | func newKey(rand io.Reader) (*Key, error) {
73 | privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand)
74 | if err != nil {
75 | return nil, err
76 | }
77 | return newKeyFromECDSA(privateKeyECDSA), nil
78 | }
79 |
80 | func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) {
81 | k, err := randFieldElement(c, rand)
82 | if err != nil {
83 | return nil, err
84 | }
85 |
86 | priv := new(PrivateKey)
87 | priv.PublicKey.Curve = c
88 | priv.D = k
89 | priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes())
90 | return priv, nil
91 | }
92 | func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) {
93 | params := c.Params()
94 | b := make([]byte, params.BitSize/8+8)
95 | _, err = io.ReadFull(rand, b)
96 | if err != nil {
97 | return
98 | }
99 |
100 | k = new(big.Int).SetBytes(b)
101 | n := new(big.Int).Sub(params.N, one)
102 | k.Mod(k, n)
103 | k.Add(k, one)
104 | return
105 | }
106 | func newKeyFromECDSA(privateKeyECDSA *ecdsa.PrivateKey) *Key {
107 | id := uuid.NewRandom()
108 | key := &Key{
109 | Id: id,
110 | Address: crypto.PubkeyToAddress(privateKeyECDSA.PublicKey),
111 | PrivateKey: privateKeyECDSA,
112 | }
113 | return key
114 | }
115 | ```
116 |
117 |
118 |
119 | Get Private Key => Get Public Key by Private Key => Get Address by Public Key
120 |
--------------------------------------------------------------------------------
/ethereum/ethereum-trie.md:
--------------------------------------------------------------------------------
1 | # Trie
2 |
3 |
4 |
5 | Trie (Merkle Patricia Tree, also known as MPT) is a tree structure used to encrypt and store any (key, value) data pair in ethereum. Its insertion, search and deletion efficiency are all O(log(N)), but it is simpler and easier to understand than other tree structures such as red-black trees, and it also has the characteristics of Merkle trees.
6 |
7 |
8 |
9 | Ethereum accounts have multiple attributes (balance, code, storage information), and attributes (status) need to be updated frequently. Therefore, a data structure is needed to meet several requirements:
10 |
11 | 1. A new tree root can be quickly calculated after performing an insert, modify, or delete operation without recalculating the entire tree.
12 | 2. Even if the attacker deliberately constructs a very deep tree, its depth is limited. Otherwise, an attacker could perform a denial of service attack by deliberately building a tree deep enough that each tree update is extremely slow.
13 | 3. The root value of the tree depends only on the data, not on the order of updates. Updating in a different order, or even recomputing the tree from scratch will not change the root value of the tree.
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | ### Normal Trie
22 |
23 | > Trie, also known as prefix tree or **dictionary tree**, is an ordered tree used to save associative arrays, the keys of which are usually strings. Unlike a binary search tree, the key is not stored directly in the node, but is determined by the node's position in the tree. All descendants of a node have the same prefix, which is the string corresponding to this node, and the root node corresponds to the empty string.
24 |
25 | 
26 |
27 | In the figure above, each node is actually just a part of the key, or a character of the key. When traversing down according to a certain key until the last character of the key, the value corresponding to the key is also found.
28 | This way of looking up value is exactly the same as looking up a dictionary m
29 |
30 |
31 |
32 | 
33 |
34 | This is how we save 8 key-value pairs.
35 |
36 | ```text
37 | Key value
38 | 6c0a5c71ec20bq3w 5
39 | 6c0a5c71ec20CX7j 27
40 | 6c0a5c71781a1FXq 18
41 | 6c0a5c71781a9Dog 64
42 | 6c0a8f743b95zUfe 30
43 | 6c0a8f743b95jx5R 2
44 | 6c0a8f740d16y03G 43
45 | 6c0a8f740d16vcc1 48
46 | ```
47 |
48 | #### **Merkle Tree**
49 |
50 | Merkle Tree, also commonly called Hash Tree, as the name suggests, is a tree that stores hash values.
51 | The main function of the Merkle Tree is that when the Top Hash is obtained, the hash value represents the information summary of the entire tree. When any data in the tree changes, the value of the Top Hash will change. The value of Top Hash will be stored in the block header of the blockchain.
52 |
53 | 
54 |
55 |
56 |
57 | ### Ethereum Trie
58 |
59 | Every time Ethereum executes a transaction, the state of the world corresponding to Ethereum changes. As a public chain platform, Ethereum has a large number of states corresponding to a large number of contracts. Rebuilding the state tree every time a state change occurs will undoubtedly consume huge computing resources. To solve this problem, Ethereum proposes a method of incrementally modifying the state tree. Every time the state of Ethereum changes, the original MPT tree will not be modified, but some branches will be created, as shown in the figure below;
60 |
61 |
62 |
63 | 
64 |
65 | Every time the state of Ethereum changes, it will only affect a small number of nodes in the world state MPT tree. The newly generated world state tree only needs to recalculate the hashes of a small number of affected nodes and the nodes connected to them.
66 |
67 | The state of Ethereum is very suitable for storage by MPT tree. The characteristics of MPT tree are very consistent with the characteristics of Ethereum state. When using MPT tree to store the state of Ethereum, it can bring the following advantages;
68 |
69 | 1. When the balance of an account changes, the hash of the corresponding path also changes, and then the hash value on the corresponding path is updated from the bottom up until the State Root, so that the minimum number of hashes can be calculated.
70 | 2. The full node in Ethereum maintains an incremental MPT state tree, because each block modifies only a small part of the world state. **Incremental modification** is not only conducive to block rollback, but also saves overhead.
71 | 3. Temporary block forks are common in Ethereum, but due to the complexity of Ethereum smart contracts, it is difficult to roll back the state according to the contract code if the original state is not recorded.
--------------------------------------------------------------------------------
/ethereum/pos.md:
--------------------------------------------------------------------------------
1 | # PoS
2 |
3 |
4 |
5 | The consensus mechanism is the method to ensure the consistency of each transaction in the blockchain.
6 | As an ordinary user, it is very difficult to run a full node to verify and record data on the blockchain.
7 | At present, to run an Ethereum full node, at least 800G of data must be stored, and the number is still increasing. The computing power of Ethereum miners is becoming more and more concentrated, and the full nodes are also becoming more and more concentrated. This is obviously detrimental to the security of the entire protocol.
8 |
9 | One of the goals of Ethereum 2 is to allow more ordinary people to participate in the consensus mechanism, and to make it easier for more people to run an Ethereum node.
10 |
11 | Therefore, Ethereum 2 introduces these two points:
12 |
13 | 1. POS
14 | 2. shard
15 |
16 |
17 |
18 | ### Proof of Stake
19 |
20 | The consensus algorithm used by Ethereum, Bitcoin and many mature blockchains is POW, Proof of work, and proof of work. Participating in POW is what we often call mining.
21 |
22 | POW participants have to invest a lot of money to buy hardware, and continue to consume electricity to compete to generate blocks and get rewards.
23 |
24 | POW can easily lead to the concentration of computing power to professional miners.
25 |
26 | The participants of POS are called validators—verifiers.
27 |
28 | Validator does not need to purchase special hardware and consume a lot of power. It only needs to run a program on an ordinary computer and pledge a part of virtual assets. On Ethereum it is 32 ETH.
29 |
30 | The entire network randomly selects participants in proportion to the number of participants' pledged assets and the length of participation to generate new blocks and receive rewards.
31 |
32 |
33 |
34 | ### Shard
35 |
36 | To improve the performance of Ethereum, we can of course expand the block size so that each block contains more data.
37 | But this will require nodes that store blocks to have larger hard disks and better network bandwidth. This further increases the cost of mining and running a node.
38 |
39 | So the Ethereum community abandoned this solution.
40 |
41 | The solution that Ethereum wants to adopt is called shard chain.
42 |
43 | Simply put, one chain is not enough, we run multiple chains
44 |
45 | There will be 64 blockchains running at the same time in Ethereum 2, which may increase in the future.
46 |
47 | Another advantage is that the node on the shard only needs to verify and save the data of the current shard, not the data of the entire Ethereum. This can make the node smaller and lighter, reduce the demand for hardware computing power and storage, enable more people to participate, and increase the decentralization and security of the entire Ethereum.
48 |
49 | Can shard be implemented under the POW mechanism?
50 |
51 | The answer is no. Because after sharding, the difficulty of destroying a single shard chain is actually reduced.
52 |
53 | The way POS solves this problem is to let the verifier pledge the ether currency, and if you find that you are sabotaging, you will be fined, or even all the tokens you pledged will be fined.
54 |
55 | But the punishment method of POW is to prevent those who do damage from digging blocks. All he loses is the electricity consumed while mining the blocks. In order to achieve the effect of POS confiscating pledges on POW, it is necessary to confiscate even the bad guys’ mining machines, which is obviously impossible.
56 |
57 | On the other hand, Ethereum's POS mechanism will randomly assign validators' shards. This mechanism also makes it impossible for vandals to stare at a certain chain for damage, thus increasing the difficulty of its attack.
58 |
59 |
60 |
61 | ### Beacon Chain
62 |
63 | The beacon chain is at the heart of Ethereum 2. Its main function is to implement the POS mechanism and coordinate and synchronize each shard chain. There is a chain to control the chain.
64 |
65 | The beacon chain has been launched on December 1, 2020, and users can already use the smart contract on Ethereum to pledge ETH to participate in POS to obtain rewards.
66 |
67 | Although the beacon chain has been launched, its current function is only to verify various basic functions of Ethereum 2 such as POS in the actual combat environment, and it does not have the ability to process transactions and execute smart contracts. Moreover, the currently pledged ETH and the rewards obtained cannot be withdrawn by the lock owner.
68 |
69 | The beacon chain and the current Ethereum blockchain run in parallel, that is, the current operation of Ethereum is basically not affected by the beacon chain.
70 |
71 |
72 |
73 | ### Next
74 |
75 | In the next stage, 64 shard chains will be launched and connected with the beacon chain to form a whole that can cooperate with each other.
76 |
77 | The current Ethereum blockchain is linked into the beacon chain. The official name is the docking.
78 |
79 | The current Ethereum blockchain will become one of the 64 shard chains, which also marks the official exit of POW mining from the stage of Ethereum.
--------------------------------------------------------------------------------
/ethereum/why-we-want-a-new-blockchain.md:
--------------------------------------------------------------------------------
1 | # 00.Why We Want a New Blockchain?
2 |
3 |
4 |
5 | #### Pros and Cons about Bitcoin
6 |
7 | Despite some new use cases, such as China developing a crypto RMB based on blockchain and claiming that government allocations can reach the grassroots without any third-party involvement, some people's perception of blockchain is still getting rich overnight and gambling.
8 |
9 | The high valuation of Bitcoin, which is the highest valued cryptocurrency, has largely influenced people's fascination with blockchain technology. However, from 2022 to 2023, the price of Bitcoin fell by about 70% and the financing of the blockchain industry suffered a significant decline as a result.
10 |
11 | A decade ago, from 2012 to 2013, the price of Bitcoin increased dramatically, going from $12 to $1,200. This sparked interest in the technology behind it and countless people began to pursue the technology architecture of Bitcoin, which has since become an industry standard.
12 |
13 | In short, the operation of Bitcoin is as follows.
14 |
15 | - Create a new Wallet.
16 |
17 | 1. Creating a Bitcoin wallet is equivalent to registering a tradeable account on the Bitcoin system. The wallet includes two key pieces of information: a Public Key and a Private Key. The public key can be made public and anyone can send Bitcoins to that address, similar to a bank account. The private key can be used to sign transactions, similar to a password.
18 | 2. https://github.com/bitcoin/bitcoin/blob/master/src/wallet/wallet.cpp
19 | 3. [http://bitaddress.org](https://link.zhihu.com/?target=http%3A//bitaddress.org)
20 |
21 | - Create a New Bitcoin token.
22 |
23 | 1. Transaction Collection: Bitcoin miners gather all unconfirmed transactions, as a "block".
24 | 2. Proof-of-Work: The miner calculates a unique hash value. The miner compares the hash value with a difficulty target (such as the number of leading zeros).
25 | 3. Transaction Confirmation: The block can be submitted to the Bitcoin network, and all transactions contained in it will be confirmed, the miner receives a certain amount of new bitcoins as a reward.
26 |
27 | - Send token to another account.
28 |
29 |
30 |
31 | We can conclude several things:
32 |
33 | 1. The security of transactions greatly depends on the current total computing power and the distribution of computing power in the blockchain.
34 | - If there is only one block and one miner, then the blockchain degenerates into a local database with no actual meaning to its data.
35 | - If a blockchain project's blocks and miners all belong to the same political organization or company, then the blockchain degenerates into a centralized database with no essential difference from using a traditional database, and even slower.
36 | 2. In order to maintain a decentralized blockchain, incentives are needed, such as tokens similar to Bitcoin, or else no one will waste their valuable computing resources on the blockchain.
37 | 3. The higher the economic value of the token, the more people will join the blockchain.
38 | 4. Bitcoin has only one practical function, transfer of funds.
39 |
40 |
41 |
42 |
43 | #### Try to add new features for Bitcoin: Counterparty
44 |
45 | There's an interesting fact that you can make a Bitcoin transfer to yourself. This may seem like a silly thing to do because you have to pay a fee, but it actually serves a purpose.
46 |
47 | In 2014, there was a difference of opinion within the Bitcoin community on what Bitcoin and blockchain were for. A lot of people, including some influencers, agreed that Bitcoin should only focus on transfers, and that blockchain was just for accounting purposes(In Bitcoin).
48 |
49 | However, there were also those who believed that blockchain should have other uses. Looking back now, it's obvious that this was the case, as blockchain's unalterable properties are extremely valuable, and since it has already provided such excellent support for the highly accurate money transfer business, why not develop other businesses as well? In theory, any internet business could migrate their operations to the blockchain (for example, the tweets you send can't be deleted or modified by anyone).
50 |
51 | With this in mind, Counterparty started trying to store more data on the Bitcoin blockchain. Their goal was to simply publish the data to the blockchain and then use other read interfaces to access the data and process it themselves.
52 |
53 | The specific method was to transfer Bitcoin to their own account, and in this transaction, they would place their business data in the special field OP_Return of that transaction, and then spread the transaction, waiting for their business data to be stored by the miner.
54 |
55 | This was obviously a hack-like solution. OP_Return is not designed for this. When this method was publicly announced, a lot of criticism emerged.
56 |
57 | "Counterparty didn't participate in the existing community, they just flipped the switch and started using the Bitcoin P2P nodes as extra data storage."
58 |
59 | https://www.btcstudy.org/2022/07/18/dapps-or-only-bitcoin-transactions-the-2014-debate/
60 |
61 | This is somewhat reasonable, as Counterparty essentially inserts its own data into the Bitcoin network, and therefore, all Bitcoin miners are required to provide storage services for Counterparty's data. This doesn't seem ideal.
62 |
63 |
64 |
65 | **So, what should engineers do?**
66 |
--------------------------------------------------------------------------------
/ethereum/private-key-secp256k1.md:
--------------------------------------------------------------------------------
1 | # Privaty Key: secp256k1
2 |
3 | Elliptic Curve Cryptography (ECC) is a public-key cryptographic algorithm that utilizes the discrete logarithm problem on elliptic curves to achieve secure communication and encryption.
4 |
5 | In ECC, each participant has a public key and a private key. The public key is used for encryption and signature verification, while the private key is used for decryption and signing. The private key is a random number, and the public key is the product of the private key and a point on the elliptic curve. Here's a simple example:
6 |
7 | Let's say we choose an elliptic curve, such as secp256k1, with the following parameters:
8 |
9 |
10 |
11 | ```go
12 | p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
13 | a = 0
14 | b = 7
15 | G = (x, y)
16 | x = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
17 | y = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
18 | n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
19 | h = 1
20 | ```
21 |
22 |
23 |
24 | Here, `G` is a base point on the elliptic curve, also known as a generator point, and `n` is the order of the base point, which means adding the base point to itself `n` times will result in the identity element.
25 |
26 | Now, let's generate a public-private key pair. First, we randomly choose a private key `d`, say `12345`. Then, we multiply the base point `G` by the private key `d` to obtain the public key `Q`:
27 |
28 | ```go
29 | Q = d * G = (xq, yq)
30 | (xq, yq) = d * (x, y) mod p
31 | ```
32 |
33 |
34 |
35 | Plugging in `d=12345` and `G=(x,y)`, we get:
36 |
37 | ```
38 | (xq, yq) = 12345 * (x, y) mod p
39 | xq = 0xf00f92b4e8b4c4f9d4d4ce4ba77eaa18b49c3a41fa47eeeb79f42bb41dfedc18
40 | yq = 0x58b41f8b62c44e79aafa5d0a6f9362965a5c6a5d0e56df186b35eb66691dcb21
41 | ```
42 |
43 | Now, we have a public-private key pair, where the private key is `d=12345` and the public key is `(xq, yq)`.
44 |
45 |
46 |
47 | ### Ethereum
48 |
49 | There is no particular reason why Ethereum uses the spec256k1 curve, mainly because the security of this curve has been verified by Bitcoin, and there are a large number of third-party libraries that already support this algorithm.
50 |
51 | secp256k1:
52 |
53 | - y² = x³ + 7
54 | - R:2^256 - 2^32 - 977
55 | - Base point:G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)
56 | - n:0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
57 |
58 |
59 |
60 | If k=2,the result should be 2G.
61 |
62 | ```
63 | G = (0, 7)
64 | 2G = G + G = (x3, y3)
65 | ```
66 |
67 |
68 |
69 | If we use addition calculation, then we directly calculate the address of the public key as (x3=0, y3=14), but unfortunately, the coordinates of the public key obtained by this method are not on the curve y² = x³ + 7. On elliptic curves, we will modify the definition of point plus.
70 |
71 | The self-summation of points on the elliptic curve is the symmetric point along the y-axis to the intersection point of the tangent of the curve and the curve.
72 |
73 | We will use mathematics to prove that the calculation of this point is not complicated.
74 |
75 | for a point(x1, y1},
76 |
77 | ```go
78 | y' = (3 * x²) / (2 * y)
79 |
80 | // use x1 and y1= sqrt(x³ + 7),
81 | k = y' = (3 * x1²) / (2 * y1)
82 | ```
83 |
84 | Use y - y1 = k(x - x1)
85 |
86 | ```go
87 | y - y1 = k * (x - x1)
88 | k = (3 * x1²) / ( 2 * y1)
89 |
90 | // remove y
91 | (k * (x - x1))^2 = x³ + 7
92 |
93 |
94 | x³ - k² * x² + (2kx1 - 2ky1) * x + b - (kx1 - y1)² = 0
95 | ```
96 |
97 | A cubic equation whose solution corresponds to the abscissas x1 , x2 , x3 of the three intersection points of the straight line and the elliptic curve
98 |
99 | According to Vieta's Formulas, the three roots x1 , x2 , x3 of the cubic equation have the following relationship:
100 |
101 | ```go
102 | x1 + x2 + x3 = - b / a = k ^ 2
103 |
104 | // x1 = x2
105 | k = y' = (3 * x1²) / (2 * y1)
106 |
107 | // we get the result.
108 | x3 = k^2 - 2x1
109 | y3 = k(x1 - x3) - x1
110 | ```
111 |
112 |
113 |
114 | In Ethereum, the base point is usually G=(0,1). The process for generating the public key is as follows:
115 |
116 | 1. Represent the private key as a 32-byte (256-bit) integer.
117 | 2. Use the private key to multiply the elliptic curve base point to get the public key point. Specifically, the public key point is the scalar product of the private key and the base point. The formula is: public key point = private key × G.
118 | 3. The public key point is another point on the elliptic curve, consisting of x and y coordinates. These coordinates are both 256-bit integers and can be represented as hexadecimal strings.
119 |
120 | After generating the public key, Ethereum hashes it to produce a shorter address. This process is called the ripemd160 hash. Essentially, it uses a hashing function to convert the public key to a 20-byte address, which is typically represented as a hexadecimal string for an Ethereum address. The prefix for an Ethereum address is typically 0x, indicating it is a hexadecimal number.
121 |
122 | It's important to note that the Ethereum address is actually a hash of the public key, not the public key itself. This hashing mechanism makes Ethereum addresses shorter and more convenient for transactions and storage.
123 |
124 |
125 |
126 | ### Address
127 |
128 | In the elliptic curve algorithm, the public key is derived from the private key and the elliptic curve base point. Since the private key is a 256-bit random number, the probability of two different private keys generating the same public key is very low, even among all the possible private keys in the universe. Therefore, the uniqueness of the public key is generally guaranteed.
129 |
130 | However, the public key does not necessarily correspond uniquely to an address. In Ethereum, the address is actually a hash of the public key. The hash function converts the public key into a 20-byte address, but different public keys may produce the same hash value, leading to address collisions.
131 |
132 | To avoid this, Ethereum uses a very large address space, typically represented as 2 to the power of 160. This means that in theory, there can be approximately 1.46×10 to the power of 48 possible addresses, making the probability of address collisions very low. Additionally, Ethereum addresses typically check and reject new addresses that are the same as existing addresses, further reducing the likelihood of address collisions and ensuring the uniqueness of addresses.
133 |
134 |
135 |
136 | ### Summary
137 |
138 | 1. The private key of Ethereum can quickly calculate the public key.
139 | 2. It is almost impossible to deduce the private key from the public key.
--------------------------------------------------------------------------------
/ethereum/cross-chain.md:
--------------------------------------------------------------------------------
1 | # Cross Chain
2 |
3 | For a long period of time in the early days of the industry, blockchain technology was based on the development of a single chain. At that time, it was generally recognized that the performance optimization and technical upgrade of the blockchain can be completed on a single chain. Once the members of the chain cannot reach an agreement on the development direction of the project, it can only be solved by hard forking or redesigning a chain.
4 |
5 | It was not until 2012 that Ripple Labs proposed the Inter Ledger protocol to solve the coordination problem between different blockchain systems; in 2013, Herlihy proposed the atomic transfer (atomic transfer) scheme on the forum, which became an improved scheme after improvement. One main cross-chain mode, namely the hash lock mode.
6 |
7 | More innovations followed, such as Litecoin, BitShares, and Ethereum, which accelerated the sense of crisis in the Bitcoin core development team. Therefore, in October 2014, BlockStream clearly proposed the concept of side chain for the first time.
8 |
9 | In 2017, cross-chain projects Polkadot and Cosmos proposed a plan to build a cross-chain basic platform, through which all blockchain applications can be compatible.
10 |
11 |
12 |
13 | ### Tendermint
14 |
15 | Cosmos can effectively address the existing problems of Bitcoin and Ethereum, and Cosmos proposes targeted solutions.
16 |
17 | Bitcoin: The code base is very monolithic. All three layers — network, consensus, and application — are mixed together. And the Bitcoin scripting language is limited and user-unfriendly.
18 |
19 | Ethereum: By turning the application layer into the Ethereum Virtual Machine (EVM). Virtual machines are able to process smart contracts, and any developer can deploy smart contracts to the open system of the Ethereum blockchain to build decentralized applications (dApps). But it does not simplify the development of the blockchain itself. It also has the disadvantages of limited scalability, relatively low flexibility granted to developers, and limited sovereignty per application.
20 |
21 | Therefore, Cosmos proposes Tendermint, which is a solution that packages the network and consensus layers of the blockchain into a common engine, allowing developers to focus on application development rather than complex underlying protocols, making it easy to get started.
22 |
23 | While Tendermint is ready for public or private blockchains and proposes POS, it has instant finality: as long as more than one-third of the validators are honest (Byzantine), a fork will never be created. Users can be sure that their transactions are completed immediately after the block is created (something that cannot be done in proof-of-work blockchains such as Bitcoin and Ethereum) and with high security.
24 |
25 |
26 |
27 | ### IBC
28 |
29 | The full name is INTER‑BLOCKCHAIN COMMUNICATION PROTOCOL (inter-chain communication protocol). As the name suggests, it is a communication protocol between chains, which is equivalent to the TCP/IP protocol on the Internet.
30 |
31 | So how does the IBC work? It first needs a middleman-like role called Relayer. Before officially crossing the chain, it first needs to request a connection (Connection) from the two chains and establish a channel (Channel). This channel is bidirectional and bound, because the channel needs to be assigned a unique ID and the number of channels that have been applied for by different chains is different, so we will see that the same channel is assigned different IDs in different chains (For example, the most commonly used channel between Cosmos Hub and Osmosis is Cosmos Hub/Channel-141 <=> Osmosis/Channel-0), when the channel is established, communication can begin.
32 |
33 | Now that you two fellow villagers can start chatting, do you need to find a topic for chatting? Similarly, the content transmitted by IBC also needs to carry the "topic" (Port). For example, the "topic" agreed upon by both parties in the Cosmos ecological token cross-chain is transfer. When you want to cross from chain A to chain B, you first need to initiate a specific cross-chain transaction on chain A; after the transaction is confirmed by chain A, Relayer will forward the transaction and the relevant proof (Proof) to B B chain; B chain then verifies the transaction and its proof, and if it is normal, it will perform related operations according to the established logic. Students who want to learn more can see the official introduction of Cosmos.
34 |
35 | Hey, wait, does my coin crossing from A to B mean that this coin has disappeared from the A chain? Not necessarily, we can look at the specific process:
36 |
37 | You initiate a cross-chain transaction, intending to cross 0.01 OSMO from Osmosis to Cosmos Hub. Because currently Cosmos Hub/Channel-141 <=> Osmosis/Channel-0 is the most commonly used channel, and the agreed "topic" of token cross-chain is transfer. So you specify the sourceChannel as channel-0, the sourcePort as transfer, and the payee on the Cosmos Hub as cosmos186440u3pwts7s3jljngak37xnmy5le8nztf9az
38 |
39 | When the node receives and recognizes that your transaction is a cross-chain transaction and also knows that you want to go from Osmosis to Cosmos Hub, it will not be destroyed at this time, but will transfer your OSMO to the custodial account. Where did this custodial account come from? Is it controlled by an external entity? Don't worry, it's not. The calculation logic of the custody account is:
40 |
41 | ```
42 | pubkey = sha256(
43 | Buffer.from("ics20-1", "utf-8")
44 |
45 | + Buffer.from([0])
46 | + Buffer.from(`${sourcePort}/${sourceChannel}`, "utf-8")
47 | ).slice(0, 20)
48 |
49 | Bech32.encode(addressPrefix, pubkey)
50 | // At this point addressPrefix: "osmo", sourcePort: "transfer", sourceChannel: "channel-0"
51 | ```
52 |
53 | Therefore, we can calculate that the custody account is osmo1a53udazy8ayufvy0s434pfwjcedzqv347h34au. If you are interested, you can click on this address to see how many coins have gone from Osmosis/Channel-0 to Cosmos Hub
54 |
55 | Then Relayer will forward this cross-chain message to Cosmos Hub. After Cosmos Hub receives this message and fully verifies it, it will directly mint 0.01 ibc/14F9BC3E44B8A9C1BE1FB08980FAB87034C9905EF17CF2F5008FC085218811CC to the address cosmos186440u3pwts7s3jljngak37xnmy5le8nztf9az. Not OSMO? What the hell is this? In fact, this is the subtlety. Because this currency is minted out of thin air, and its "code name" (denom) cannot coincide with the existing currency, so it can be obtained in the following way:
56 |
57 | ```
58 | "ibc/" + sha256(Buffer.from(`${dstPort}/${dstChannel}/${originDenom}`, 'utf-8')).toString("hex").toUpperCase()
59 | // At this point dstPort: transfer, dstChannel: channel-141, originDenom: uosmo
60 | ```
61 |
62 | Of course, you don’t need to see this unreadable code name during the use of Cosmos Hub. The wallet or browser will intelligently replace its name with OSMO.
63 |
64 | So far, by locking assets in Osmosis, and then minting assets in Cosmos Hub, you have crossed over your assets, and now you can play happily. So what if you want to go back to the Osmosis chain? akin:
65 |
66 | You initiate another cross-chain transaction, specifying sourceChannel as channel-141, sourcePort as transfer and the payee on Osmosis as osmo186440u3pwts7s3jljngak37xnmy5le8n2s64ts
67 | After the node receives the transaction, it detects that you want to return to Osmosis from the Cosmos Hub, so it will directly destroy the coin that was minted out of thin air at this time.
68 | Then, after the Relayer forwards the cross-chain message to Osmosis, Osmosis will transfer the OSMO previously placed on the custodial address to your receiving address after full verification.
69 | Students who want to know more details can also find the answer from the specification and source code
70 |
71 | But if you are smart, you will definitely notice a detail, the process of minting coins out of thin air includes ChannelID. Isn't that equivalent to saying that the same currency will become different currencies when it comes through different channels, and they cannot share liquidity? Yes, this is why there are so many channels between different browser chains, but there is only one with traffic.
--------------------------------------------------------------------------------
/ethereum/gas-eip-1559.md:
--------------------------------------------------------------------------------
1 | # EIP-1559
2 |
3 | ### Why need Token in BlockChain?
4 |
5 | In blockchain technology, tokens are units of value or digital assets that are stored and transferred on a blockchain network. Tokens can be used to represent various things, such as cryptocurrencies, digital assets, voting rights, or access to a particular service or platform.
6 |
7 | Tokens are necessary in blockchain for several reasons:
8 |
9 | 1. Facilitating Transactions: Tokens serve as a means of exchange and can be used to facilitate transactions within a blockchain network. For example, in a cryptocurrency blockchain, tokens are used to buy and sell goods and services.
10 | 2. Enabling Smart Contracts: Smart contracts are self-executing contracts with the terms of the agreement between buyer and seller being directly written into lines of code. Tokens are used in smart contracts as a way to execute the terms of the agreement.
11 | 3. Security and Transparency: Tokens can enhance security and transparency within blockchain networks. The use of tokens helps to prevent fraud and other forms of illegal activity by creating a clear and secure record of transactions.
12 | 4. Community Building: Tokens can also be used to incentivize community members to participate in a blockchain network, such as through mining or staking. This helps to build a strong and engaged community that can help to drive the success of the network.
13 |
14 | Overall, tokens are an essential component of blockchain technology, as they serve as the building blocks for the creation of decentralized applications, digital assets, and cryptocurrencies.
15 |
16 | I think the most important reason is that the blockchain is a distributed service that requires a large number of miners to join. Then there needs to be something to seduce others.
17 |
18 |
19 |
20 | ### Wei and Ether
21 |
22 | Both Wei and Ether are units of cryptocurrency in the Ethereum blockchain network.
23 |
24 | Wei is the smallest unit of Ether, similar to Satoshi in Bitcoin. 1 Ether is equal to 10^18 Wei, therefore, 1 Wei is equal to 0.000000000000000001 Ether.
25 |
26 | Ether, the native cryptocurrency in the Ethereum network, is generated through mining and trading activities.
27 |
28 | Smart contracts on the Ethereum network can pay transaction fees in Ether, which are paid in the form of Wei. Transaction fees are collected by miners to incentivize them to validate transactions on the network.
29 |
30 | Below is a more detailed description of how Wei and Ether are minted, modified, queried and deleted:
31 |
32 | 1. Generation: Ether is generated through the mining process of the Ethereum network. Mining is a computationally intensive process designed to verify new transactions and add them to the blockchain. Miners earn new ether by solving complex mathematical puzzles, and they are also rewarded with transaction fees and other rewards.
33 |
34 | 2. Modification: Ether is stored on the Ethereum blockchain and cannot be modified or deleted. They can only be moved by executing a new transaction. When a transaction is executed, ether is transferred from one account to another, which creates a new transaction record on the blockchain.
35 |
36 | 3. Query: You can query the balance and transaction records of Ethereum and Wei through the blockchain browser on the Ethereum network. Users can use the Ethereum Wallet app or other third-party apps to check their account balances.
37 |
38 | 4. Deletion: Ether and Wei are digital assets on the Ethereum blockchain and cannot be deleted. However, if an account is deemed defunct or no longer in use, its balance may be considered "dead" and removed from the blockchain. This will show up on the blockchain explorer as the account balance is zero.
39 |
40 |
41 |
42 | ### Gas
43 |
44 | Gas represents the computational cost required to complete an operation. When a transaction or smart contract is submitted to the Ethereum network, it needs to consume a certain amount of Gas, which will eventually be consumed by miners.
45 |
46 | Ethereum needs Gas for the following reasons:
47 |
48 | 1. Prevent DDoS attacks: The Ethereum network needs to calculate the cost of each operation, so a certain Gas fee needs to be paid when performing the operation, which can prevent malicious users from exhausting network resources through a large number of meaningless operations.
49 |
50 | 2. Network economics: Since the Ethereum network is distributed, nodes need to communicate and collaborate with each other to reach consensus. By paying Gas, the efficient use of network resources can be ensured, thereby improving the economy of the network.
51 |
52 | 3. Encourage miners: Gas fees are one of the sources of income for Ethereum miners. Since miners need to consume electricity and computing power to verify transactions and blocks, paying enough gas fees can encourage miners to verify transactions faster and pack them into blocks.
53 |
54 |
55 |
56 | ### EIP-1559
57 |
58 | From its purpose, it is a proposal to try to reduce transaction fees.
59 |
60 | In the past, the efficiency of Ethereum was indeed not high. The reason is Ethereum's "first price auction".
61 |
62 | When transactions are congested, Ethereum adopts the first-price auction principle to select transactions, in other words, "the one with the highest price wins". If 10 people bid 1 to 10 respectively, then miners will naturally choose the five transactions with bids 6 to 10 to be uploaded to the chain.
63 |
64 |
65 |
66 | 
67 |
68 | The result is that the more congested the network is, the more users are anxious to confirm the transaction, and the higher the transaction fee paid by the user.
69 |
70 |
71 | The starting point of EIP-1559 is to change the above situation - this method is the uniform price auction.
72 |
73 | Continuing to consider the previous situation, 10 people bid 1-10 respectively, and the miners choose 5 packs.
74 |
75 | In the uniform price auction, each person who successfully goes on the chain does not need to pay his own asking price, but only needs to pay the bid of the person with the lowest bid among all the packaged transactions, and then the miners get the money as a reward. In this way, people who bid 6-10 are still packaged and uploaded to the chain, but each person only needs to pay 6.
76 |
77 | 
78 |
79 |
80 |
81 | This proposal is naturally good for users. For them, transaction fees are reduced
82 | For miners, this auction method must be bad, because the income is significantly lower.
83 |
84 | So a miner can do this. When he finds that the price of this round of packaging is obviously too low, such as 1, he might as well generate a transaction to raise the price by himself, such as 3!
85 | When the network is already congested, these transactions generated by miners occupy the limited resources.
86 |
87 | ##### Burn base fee
88 |
89 | How to do it?
90 |
91 | In reality, there may not be many ways, but in the blockchain, there is really a way:
92 |
93 | Miners do not receive fees, but burn instead. If the handling fee needs to be destroyed, then it is not feasible for the miners to send the transaction by themselves; now sending the transaction becomes really burning their own money, and the increased handling fee will not fall into their own hands.
94 |
95 | EIP-1559 changed this handling fee to a word called basic fee. The basic fee must be destroyed.
96 | But there is also a concept of tipping at the same time. If the user is really in a hurry, you can send a tip. Tips will be received by miners.
97 |
98 | Even, this plan has another advantage, the total number of Ethereum will decrease, then the single value of Ethereum will rise in the long-term trend.
99 |
100 | But is this really the case?
101 | From the perspective of miners, they are not subordinates or hired by anyone - they are one of the most important partners of Ethereum, because they provide the most important computing power in a PoW blockchain.
102 |
103 | For miners, the base fee will be burned, so they can ask traders "unless you give us enough tips, I will not accept your transaction even if you give the base fee."
104 |
105 | [According](https://ultrasound.money/) to data from Ultra Sound Money, 7.67 ETH is burned every minute, and up to 11,042 ETH is burned each day. At current rates, approximately 4 million ETH is burned every year. However, the blockchain currently emits about 5.4 million ETH per year.
--------------------------------------------------------------------------------
/ethereum/smart-contracrt.md:
--------------------------------------------------------------------------------
1 | # Smart Contract
2 |
3 | Smart contracts are one of the most important concepts of Ethereum.
4 | Bitcoin proves that data can be immutable through blockchain technology. Ethereum also puts the code on the blockchain, and has a built-in VM that can run the code.
5 | Unalterable code and data, coupled with the operating environment, means that the Ethereum provides a complete, uncontrolled, immutable computer.
6 |
7 | Imagine an Apple Store, where the app running logic is all open and will not be modified by anyone. There, in theory, we can put all the apps into this app store and re-implement it again.
8 |
9 | This is web3.
10 |
11 |
12 |
13 | ### Context
14 |
15 | "Smart contracts" are not real contracts, nor are they particularly smart, they just run code on the blockchain.
16 |
17 | Smart contracts are kept in a special kind of account on the Ethereum network. We have user accounts and can also have smart contract accounts.
18 |
19 | Smart contract accounts are:
20 |
21 | - address
22 | - Balance (how much is there: Ether)
23 | - state: The current state of all variables and variables declared in the smart contract. In fact, the easiest way to understand smart contracts can be compared to instantiating objects of a class, the only difference is that this object will always exist in the blockchain network, which is equivalent to a small database
24 | - the code
25 |
26 | Smart contracts can call other smart contracts. A smart contract typically consists of the following components:
27 |
28 | 1. Code: The code is the set of instructions that define the logic and behavior of the contract. It is written in a programming language that is compatible with the blockchain platform on which the contract is deployed.
29 | 2. State: The state is the current status of the contract, including the values of all variables and data structures used in the code. The state is updated each time the contract is executed.
30 | 3. Address: Each smart contract is assigned a unique address on the blockchain, which serves as its identifier.
31 | 4. Events: Events are messages that the contract can emit when certain conditions are met. These messages can be used to trigger other contracts or to notify external applications of important events.
32 | 5. Functions: Functions are the methods that can be called to interact with the contract. They are defined in the code and can be accessed by other contracts or by external users.
33 | 6. Gas: Gas is the fee paid by users to execute a smart contract. The amount of gas required for a transaction depends on the complexity of the code and the amount of data being processed.
34 |
35 |
36 |
37 | Let us start with a demo.
38 |
39 | ```go
40 | contract Counter {
41 | uint counter;
42 |
43 | function Counter() public {
44 | counter = 0;
45 | }
46 | function count() public {
47 | counter = counter + 1;
48 | }
49 | }
50 | ```
51 |
52 |
53 |
54 | The code has a variable named "counter" of type uint (unsigned integer). The content (value) of the counter variable is the state of the contract. Whenever we call the count() function, the zone state of this smart contract will be incremented by 1, and this state is visible to everyone.
55 |
56 | 
57 |
58 |
59 |
60 | Ethereum supports three types of transactions:
61 |
62 | - Transfer of value (same as Bitcoin)
63 | - TO : receiving address
64 | - DATA : leave blank or leave a message
65 | - FROM : who issued
66 | - AMOUNT : how much to send
67 | - create contract
68 | - **TO : ''''(this is what triggers the creation of the smart contract)**
69 | - DATA : Contains the smart contract code compiled to bytecode
70 | - FROM : who created
71 | - AMOUNT : Can be zero or any amount of ether, it is the deposit we want to give to the contract.
72 | - Call the contract function
73 | - TO: target contract account address
74 | - DATA: Contains the function name and parameters - identifies how to call the smart contract function
75 | - FROM : who calls
76 | - AMOUNT: Can be zero or any amount of ether, for example to pay for contract services.
77 |
78 | This also means that our call to the smart contract is achieved by creating a transaction.
79 |
80 |
81 |
82 | ### Language
83 |
84 | There are several programming languages that can be used for smart contract development on various blockchain platforms. Here are some of the most common ones:
85 |
86 | 1. **Solidity**: Solidity is the most commonly used language for developing smart contracts on the Ethereum blockchain. It is a contract-oriented language that is similar to JavaScript and is designed specifically for writing smart contracts.
87 | 2. **Vyper**: Vyper is a newer language designed to address some of the security issues with Solidity. It is also used for developing smart contracts on the Ethereum blockchain.
88 | 3. **Chaincode** (Go): Chaincode, also known as smart contracts on the Hyperledger Fabric blockchain, can be developed using Go programming language.
89 | 4. **Cadence**: Cadence is a new language developed by Dapper Labs for writing smart contracts on the Flow blockchain.
90 | 5. **Rust**: Rust is a systems programming language that can be used for writing smart contracts on the NEAR Protocol blockchain.
91 | 6. **Michelson**: Michelson is a domain-specific language designed for smart contracts on the Tezos blockchain.
92 |
93 | It's worth noting that some blockchains also support multiple programming languages for smart contract development, and new languages are constantly being developed to improve the security, efficiency, and flexibility of smart contracts.
94 |
95 |
96 |
97 | ### Smart Contract Can Do Something!
98 |
99 | Smart contracts have the potential to serve real-world use cases in many ways, including:
100 |
101 | 1. Decentralized Finance (DeFi): Smart contracts can be used to automate financial transactions, such as lending and borrowing, without the need for intermediaries. This can significantly reduce costs and increase efficiency in the financial system.
102 | 2. Supply Chain Management: Smart contracts can be used to track the movement of goods and ensure their authenticity, from the manufacturer to the end-user. This can help prevent fraud and improve transparency in supply chain management.
103 | 3. Real Estate: Smart contracts can be used to automate real estate transactions, such as property transfers and lease agreements. This can reduce the time and cost associated with traditional real estate transactions.
104 | 4. Identity Verification: Smart contracts can be used to verify the identity of individuals, which can be useful in areas such as voting, access to government services, and online transactions.
105 | 5. Gaming and Digital Collectibles: Smart contracts can be used to create digital assets, such as in-game items and collectibles, that are secured by the blockchain. This can prevent fraud and create a more transparent and secure gaming environment.
106 | 6. Insurance: Smart contracts can be used to automate insurance claims and payouts, which can reduce the time and cost associated with traditional insurance processes.
107 |
108 | Overall, smart contracts have the potential to significantly improve efficiency, transparency, and security in many different industries and use cases. As blockchain technology continues to evolve, we can expect to see more innovative applications of smart contracts in the future.
109 |
110 | Of course it's worth pointing out that these products aren't powerful enough to replace existing tools, they're just a possibility.
111 | The most important thing about Smart Contract is to lower the threshold for people to create cryptocurrency. We can conduct quick financing through ICO.
112 |
113 |
114 |
115 | ### But
116 |
117 | While smart contracts can theoretically do anything, they are not well suited for heavy computational work.
118 |
119 | The Ethereum World Computer is like an old slow computer that can run simple programs. Keeping Ethereum smart contracts small and simple is critical for cost and security reasons.
120 |
121 | The more computation a contract has, the more expensive it is to run it. The more complex the contract, the more likely it is that a security breach will occur. Security holes in smart contracts are difficult to fix because of the immutable nature of the blockchain.
122 |
123 |
124 |
125 | ### Questions
126 |
127 | - How is a smart contract library useful?
128 | - a smart contract library can be a very useful tool for smart contract developers, allowing them to save time, improve efficiency, ensure consistency, and enhance security. It can also help to promote standardization and best practices in the development of smart contracts.
129 |
--------------------------------------------------------------------------------
/ethereum/erc20-token.md:
--------------------------------------------------------------------------------
1 | # ERC 20
2 |
3 | Let us try to build a homogeneous token!
4 |
5 | A homogeneous token (ERC-20) is a token created on the Ethereum (Ethereum) blockchain. Each token is exactly the same on the blockchain and has the same value and attributes. For example, if you buy 10 ERC-20 tokens, the tokens are the same, there is no difference.
6 |
7 | Non-homogeneous tokens (NFTs) are different. Each NFT is unique, unique, and has unique attributes and values. For example, a piece of digital artwork could be an NFT that has a unique design, time of creation, and artist information, attributes that set it apart from other NFTs or tokens.
8 |
9 | As another example, a real estate developer could use NFTs to represent their real estate projects. Each NFT represents a unique real estate unit with unique attributes such as location, floor area, style, design and selling price.
10 |
11 | In conclusion, fungible tokens are fungible and indistinguishable, while non-fungible tokens are unique, each with its own value and attributes.
12 |
13 | **In fact, before the launch of NFT, all tokens are homogeneous.**
14 |
15 |
16 |
17 | ```go
18 | contract ERC20Interface {
19 |
20 | string public constant name = "Token Name";
21 | string public constant symbol = "SYM";
22 | uint8 public constant decimals = 18; // 18 is the most common number of decimal places
23 |
24 | function totalSupply() public constant returns (uint);
25 | function balanceOf(address tokenOwner) public constant returns (uint balance);
26 | function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
27 | function transfer(address to, uint tokens) public returns (bool success);
28 | function approve(address spender, uint tokens) public returns (bool success);
29 | function transferFrom(address from, address to, uint tokens) public returns (bool success);
30 |
31 | event Transfer(address indexed from, address indexed to, uint tokens);
32 | event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
33 | }
34 | ```
35 |
36 |
37 |
38 | Let us see how Tether (USDT) built by smart contract.
39 |
40 |
41 |
42 | ### Tether(USDT)
43 |
44 | Form this url https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7#code
45 |
46 | By the way, smart contracts themselves cannot be changed - once deployed to the blockchain, they are immutable.
47 | But there can be one or more smart contracts running together, some of which can act as "backends". In this way, we can upgrade the interaction mode between these smart contracts. Here, upgrading a smart contract does not mean modifying the code of a deployed smart contract, but replacing one of the smart contracts with another. We do this in such a way that (in most cases) the end user doesn't have to change how they interact with the dApp.
48 |
49 | So the real upgrading of smart contracts is a process in which new smart contracts replace old smart contracts. When the new smart contract is used, the old smart contract will be "abandoned" on the chain, because the old contract is immutable.
50 |
51 |
52 |
53 | USDT needs to have the following functions
54 |
55 | 1. Functions of transfer, balance inquiry and authorized consumption under ERC20 requirements
56 | 2. Token emergency suspension and restart
57 | 3. Token User Blacklist
58 | 4. The contract is conveniently upgraded and can be adapted to non-ERC20 protocol tokens
59 | 5. Token manager authority transfer
60 |
61 | ```solidity
62 | /**
63 | *Submitted for verification at Etherscan.io on 2017-11-28
64 | */
65 |
66 | pragma solidity ^0.4.17;
67 |
68 | /**
69 | * @title SafeMath
70 | * @dev Math operations with safety checks that throw on error
71 | */
72 | library SafeMath {
73 | ...
74 | }
75 |
76 | /**
77 | * @title Ownable
78 | * @dev The Ownable contract has an owner address, and provides basic authorization control
79 | * functions, this simplifies the implementation of "user permissions".
80 | */
81 | contract Ownable {
82 | address public owner;
83 |
84 | ...
85 |
86 | /**
87 | * @dev Allows the current owner to transfer control of the contract to a newOwner.
88 | * @param newOwner The address to transfer ownership to.
89 | */
90 | function transferOwnership(address newOwner) public onlyOwner {
91 | if (newOwner != address(0)) {
92 | owner = newOwner; // give this contract to another account
93 | }
94 | }
95 |
96 | }
97 |
98 | /**
99 | * @title ERC20Basic
100 | * @dev Simpler version of ERC20 interface
101 | * @dev see https://github.com/ethereum/EIPs/issues/20
102 | */
103 | contract ERC20Basic {
104 | ...;
105 | }
106 |
107 | /**
108 | * @title ERC20 interface
109 | * @dev see https://github.com/ethereum/EIPs/issues/20
110 | */
111 | contract ERC20 is ERC20Basic {
112 | ...;
113 | }
114 |
115 | /**
116 | * @title Basic token
117 | * @dev Basic version of StandardToken, with no allowances.
118 | */
119 | contract BasicToken is Ownable, ERC20Basic {
120 | using SafeMath for uint;
121 |
122 | mapping(address => uint) public balances; // This is balacne Db
123 |
124 | // additional variables for use if transaction fees ever became necessary
125 | uint public basisPointsRate = 0;
126 | uint public maximumFee = 0;
127 |
128 | /**
129 | * @dev Fix for the ERC20 short address attack.
130 | */
131 | modifier onlyPayloadSize(uint size) {
132 | require(!(msg.data.length < size + 4));
133 | _;
134 | }
135 |
136 | /**
137 | * @dev transfer token for a specified address
138 | * @param _to The address to transfer to.
139 | * @param _value The amount to be transferred.
140 | */
141 | function transfer(address _to, uint _value) public onlyPayloadSize(2 * 32) {
142 | uint fee = (_value.mul(basisPointsRate)).div(10000);
143 | if (fee > maximumFee) {
144 | fee = maximumFee;
145 | }
146 | uint sendAmount = _value.sub(fee);
147 | balances[msg.sender] = balances[msg.sender].sub(_value);
148 | balances[_to] = balances[_to].add(sendAmount);
149 | if (fee > 0) {
150 | balances[owner] = balances[owner].add(fee);
151 | Transfer(msg.sender, owner, fee);
152 | }
153 | Transfer(msg.sender, _to, sendAmount);
154 | }
155 |
156 | /**
157 | * @dev Gets the balance of the specified address.
158 | * @param _owner The address to query the the balance of.
159 | * @return An uint representing the amount owned by the passed address.
160 | */
161 | function balanceOf(address _owner) public constant returns (uint balance) {
162 | return balances[_owner];
163 | }
164 |
165 | }
166 |
167 | /**
168 | * @title Standard ERC20 token
169 | *
170 | * @dev Implementation of the basic standard token.
171 | * @dev https://github.com/ethereum/EIPs/issues/20
172 | * @dev Based oncode by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
173 | */
174 | contract StandardToken is BasicToken, ERC20 {
175 | ...
176 | }
177 |
178 | ...
179 |
180 | contract TetherToken is Pausable, StandardToken, BlackList {
181 |
182 | string public name;
183 | string public symbol;
184 | uint public decimals;
185 | address public upgradedAddress; // We use this to update Smart Contract
186 | bool public deprecated;
187 |
188 | // The contract can be initialized with a number of tokens
189 | // All the tokens are deposited to the owner address
190 | //
191 | // @param _balance Initial supply of the contract
192 | // @param _name Token Name
193 | // @param _symbol Token symbol
194 | // @param _decimals Token decimals
195 | function TetherToken(uint _initialSupply, string _name, string _symbol, uint _decimals) public {
196 | _totalSupply = _initialSupply;
197 | name = _name;
198 | symbol = _symbol;
199 | decimals = _decimals;
200 | balances[owner] = _initialSupply; // Owner Get All Token!
201 | deprecated = false;
202 | }
203 |
204 | ...
205 | }
206 | ```
207 |
208 |
209 |
210 | Tether claims that it will strictly abide by the 1:1 reserve guarantee. For every USDT token issued, its bank account will have 1 dollar of funds as a guarantee.
211 |
212 | We can see that Tether's smart contract has no constraints on its promises. And the smart contract of Tether currency can also be upgraded.
213 | In theory, the owner of Tether can withdraw any amount of USDT from its account to exchange for US dollars, and it will not be discovered by anyone.
214 |
215 | But we believe he won't. Because Tether has a noble and admirable moral bottom line. **Even if Tether does not have transparent financial audits and closed audits, it has never responded positively to everyone's doubts. .**
--------------------------------------------------------------------------------
/ethereum/mining-start.md:
--------------------------------------------------------------------------------
1 | # Mining: Start
2 |
3 | Mining involves three channels.
4 |
5 | 1. newWorkCh
6 | 2. txsCh
7 | 3. chainSideCh
8 |
9 | 
10 |
11 | Once we received the **newWorkCh**. We should start to mining.
12 |
13 | ```go
14 | //miner/worker.go:409
15 | case req := <-w.newWorkCh:
16 | w.commitNewWork(req.interrupt, req.noempty, req.timestamp)
17 | ```
18 |
19 | The **txsCh** message is triggered when a new transaction is received.
20 |
21 | ```go
22 | //miner/worker.go:451
23 | case ev := <-w.txsCh:
24 | if !w.isRunning() && w.current != nil {
25 | w.mu.RLock()
26 | coinbase := w.coinbase
27 | w.mu.RUnlock()
28 |
29 | txs := make(map[common.Address]types.Transactions)
30 | for _, tx := range ev.Txs {
31 | acc, _ := types.Sender(w.current.signer, tx)
32 | txs[acc] = append(txs[acc], tx)
33 | }
34 | txset := types.NewTransactionsByPriceAndNonce(w.current.signer, txs)
35 | w.commitTransactions(txset, coinbase, nil)
36 | w.updateSnapshot()
37 | } else {
38 | if w.config.Clique != nil && w.config.Clique.Period == 0 {
39 | w.commitNewWork(nil, false, time.Now().Unix())
40 | }
41 | }
42 | atomic.AddInt32(&w.newTxs, int32(len(ev.Txs)))
43 | ```
44 |
45 | In the process, the new transactions will be sorted according to the price and Nonce value, and after forming an ordered transaction set, they will be committed in sequence.
46 | It can be seen that the process of receiving and processing new transactions does not interfere with mining. There is also no need to consider whether the transaction has been processed, because when the transaction is duplicated, the second committed will fail.
47 |
48 | **chainSideCh**
49 |
50 | This message is triggered when a local block is added to the side chain. After receiving this message, the block in the message (that is, the block added to the side chain) is added to the "uncle block" list, and according to the current state, two uncle blocks may be selected to submit a block generation task. (This channel is the embodiment of Ethereum encouraging uncle blocks)
51 |
52 | ```go
53 | //miner/worker.go:412
54 | case ev := <-w.chainSideCh:
55 | if _, exist := w.localUncles[ev.Block.Hash()]; exist {//❶
56 | continue
57 | }
58 | if _, exist := w.remoteUncles[ev.Block.Hash()]; exist {
59 | continue
60 | }
61 | if w.isLocalBlock != nil && w.isLocalBlock(ev.Block) {//❷
62 | w.localUncles[ev.Block.Hash()] = ev.Block
63 | } else {
64 | w.remoteUncles[ev.Block.Hash()] = ev.Block
65 | }
66 | if w.isRunning() && w.current != nil && w.current.uncles.Cardinality() < 2 {//❸
67 | start := time.Now()
68 | if err := w.commitUncle(w.current, ev.Block.Header()); err == nil {//❹
69 | var uncles []*types.Header
70 | w.current.uncles.Each(func(item interface{}) bool {
71 | //...
72 | })
73 | w.commit(uncles, nil, true, start)//❺
74 | }
75 | }
76 | ```
77 |
78 |
79 |
80 | ### Set New Block Info
81 |
82 | ```go
83 | //miner/worker.go:829
84 | parent := w.chain.CurrentBlock()//Mining is to compete to dig the next block, and the block with the latest height needs to be used as the parent block
85 |
86 | if parent.Time() >= uint64(timestamp) {// Change the timestamp
87 | timestamp = int64(parent.Time() + 1)
88 | }
89 | if now := time.Now().Unix(); timestamp > now+1 {
90 | wait := time.Duration(timestamp-now) * time.Second
91 | log.Info("Mining too far in the future", "wait", common.PrettyDuration(wait))
92 | time.Sleep(wait)
93 | }
94 | num := parent.Number()
95 | header := &types.Header{
96 | ParentHash: parent.Hash(),
97 | Number: num.Add(num, common.Big1),
98 | GasLimit: core.CalcGasLimit(parent, w.gasFloor, w.gasCeil),
99 | Extra: w.extra,
100 | Time: uint64(timestamp),
101 | }
102 | if w.isRunning() {
103 | if w.coinbase == (common.Address{}) {
104 | log.Error("Refusing to mine without etherbase")
105 | return
106 | }
107 | header.Coinbase = w.coinbase// Set account to get the ETH rewards
108 | }
109 |
110 |
111 | ...
112 |
113 | err := w.makeCurrent(parent, header) // Update stateDB by transaction
114 | if err != nil {
115 | log.Error("Failed to create mining context", "err", err)
116 | return
117 | }
118 | ```
119 |
120 | ### Add Uncle Blocks
121 |
122 | We can see the code listen the chainSideCh and add a uncle blocks set. But why we need Uncle Blocks?
123 |
124 | In a distributed system, due to network delay and asynchronous communication between nodes, there is a certain delay and uncertainty. This can result in two or more miners mining a new block almost simultaneously, but only one of the blocks can be added to the blockchain.
125 |
126 | Uncle Blocks can motivate more miners to participate in the consensus process, even if their blocks are not confirmed and added to the main chain.
127 |
128 |
129 |
130 | ### PoW find Nonce
131 |
132 | ```go
133 | //miner/worker.go:508
134 | case task := <-w.taskCh:
135 | //...
136 | sealHash := w.engine.SealHash(task.block.Header())//get the hash of block
137 | if sealHash == prev {
138 | continue
139 | }
140 | interrupt()
141 | stopCh, prev = make(chan struct{}), sealHash
142 |
143 | if w.skipSealHook != nil && w.skipSealHook(task) {
144 | continue
145 | }
146 | w.pendingMu.Lock()
147 | w.pendingTasks[w.engine.SealHash(task.block.Header())] = task
148 | w.pendingMu.Unlock()
149 |
150 | if err := w.engine.Seal(w.chain, task.block, w.resultCh, stopCh); err != nil { // find nonce and send resultCh
151 | log.Warn("Block sealing failed", "err", err)
152 | }
153 |
154 | //miner/worker.go:542
155 | select {
156 | case block := <-w.resultCh:
157 | if block == nil {
158 | continue
159 |
160 | if w.chain.HasBlock(block.Hash(), block.NumberU64()) {
161 | continue
162 | }
163 | var (
164 | sealhash = w.engine.SealHash(block.Header())
165 | hash = block.Hash()
166 | )
167 | ```
168 |
169 |
170 |
171 | Finally, Broadcast the new Block.
172 |
173 | ```go
174 | //eth/handler.go:771
175 | func (pm *ProtocolManager) minedBroadcastLoop() {
176 | for obj := range pm.minedBlockSub.Chan() {
177 | if ev, ok := obj.Data.(core.NewMinedBlockEvent); ok {
178 | pm.BroadcastBlock(ev.Block, true) //❼
179 | pm.BroadcastBlock(ev.Block, false) //❽
180 | }
181 | }
182 | }
183 | ```
184 |
185 |
186 |
187 | 
188 |
189 |
190 |
191 |
192 |
193 | ### One more thing: How to use GPU to mining?
194 |
195 | Ethereum uses a hashing algorithm called Ethash, which is a memory-hard algorithm, meaning it requires a lot of memory to mine efficiently. The purpose of this algorithm design is to avoid the emergence of ASIC (application-specific integrated circuit) mining machines, so that ordinary computers can also have the opportunity to participate in mining.
196 |
197 | CPUs usually only have smaller caches, while GPUs have larger memory and higher memory bandwidth, which makes GPUs more suitable for the memory-intensive calculations required in the Ethash algorithm. In contrast, the performance of CPUs is mainly determined by the clock speed and computing power of individual cores, and their memory bandwidth is relatively small.
198 |
199 | Therefore, using GPU mining is more efficient than using CPU mining, and it is also the current mainstream method of Ethereum mining.
200 |
201 | The basic principle of the Ethash algorithm is to use a data structure called DAG (Directed Acyclic Graph) for hash calculation. This DAG is computed iteratively as a series of hash functions, each of which depends on the results of previous hash functions. Therefore, the calculation of DAG is a very memory-intensive process.
202 |
203 | Specifically, the Ethash algorithm first generates a 256MB DAG using a random number called a "hash seed". Miners then need to perform hash calculations using the DAG and some other data such as mining parameters and Nonce to find eligible blocks. Each calculation process needs to use some random data in the DAG, which needs to be stored in memory. Since the DAG is very large, a lot of memory is required to store it. The greater the amount of memory used by the miner, the faster the calculations because more data can be cached.
204 |
205 | In addition, the Ethash algorithm also designs a data structure called "cache" to speed up hash calculations. The size of the cache is determined by the hardware of the miner. A larger cache means that the miner can calculate the correct hash value faster, thus achieving higher mining efficiency.
206 |
207 | The reason why a lot of memory is needed is because the Ethash algorithm uses the DAG data structure for hash calculations, and the DAG is very large and requires a lot of memory to store it. Since miners need to frequently use DAG for hash calculations, a large amount of memory is required to cache these data, thereby improving computing efficiency.
208 |
209 | The RTX 3090, for example, has 24 GB of GDDR6X memory.
--------------------------------------------------------------------------------
/ethereum/transaction.md:
--------------------------------------------------------------------------------
1 | # Transaction
2 |
3 | The complete process of an Ethereum transaction is divided into the following steps:
4 |
5 | 1. Initiate a transaction: specify the target address and transaction amount, as well as the required gas/gaslimit
6 | 2. Transaction signature: use the account private key to sign the transaction
7 | 3. Submit the transaction: add the transaction to the transaction buffer pool txpool (the transaction signature will be verified first)
8 | 4. Broadcast transaction: notify EVM to execute, and broadcast transaction information to other nodes at the same time
9 |
10 |
11 |
12 | ### Initiate a transaction
13 |
14 | The code in internal/ethapi/api.go.
15 |
16 | ```go
17 | func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) {
18 |
19 | // Look up the wallet containing the requested signer
20 | account := accounts.Account{Address: args.From}
21 |
22 | wallet, err := s.b.AccountManager().Find(account)
23 | if err != nil {
24 | return common.Hash{}, err
25 | }
26 |
27 | if args.Nonce == nil {
28 | // Hold the addresse's mutex around signing to prevent concurrent assignment of
29 | // the same nonce to multiple accounts.
30 | s.nonceLock.LockAddr(args.From)
31 | defer s.nonceLock.UnlockAddr(args.From)
32 | }
33 |
34 | // Set some sanity defaults and terminate on failure
35 | if err := args.setDefaults(ctx, s.b); err != nil {
36 | return common.Hash{}, err
37 | }
38 | // Assemble the transaction and sign with the wallet
39 | tx := args.toTransaction()
40 |
41 | var chainID *big.Int
42 | if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) {
43 | chainID = config.ChainId
44 | }
45 | signed, err := wallet.SignTx(account, tx, chainID)
46 | if err != nil {
47 | return common.Hash{}, err
48 | }
49 | return submitTransaction(ctx, s.b, signed)
50 | }
51 |
52 | func (args *SendTxArgs) toTransaction() *types.Transaction {
53 | var input []byte
54 | if args.Data != nil {
55 | input = *args.Data
56 | } else if args.Input != nil {
57 | input = *args.Input
58 | }
59 | if args.To == nil {
60 | return types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input)
61 | }
62 | return types.NewTransaction(uint64(*args.Nonce), *args.To, (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input)
63 | }
64 |
65 | type txdata struct {
66 | AccountNonce uint64 `json:"nonce" gencodec:"required"`
67 | Price *big.Int `json:"gasPrice" gencodec:"required"`
68 | GasLimit uint64 `json:"gas" gencodec:"required"`
69 | Recipient *common.Address `json:"to" rlp:"nil"` // nil means contract creation
70 | Amount *big.Int `json:"value" gencodec:"required"`
71 | Payload []byte `json:"input" gencodec:"required"`
72 |
73 | // Signature values
74 | V *big.Int `json:"v" gencodec:"required"`
75 | R *big.Int `json:"r" gencodec:"required"`
76 | S *big.Int `json:"s" gencodec:"required"`
77 |
78 | // This is only used when marshaling to JSON.
79 | Hash *common.Hash `json:"hash" rlp:"-"`
80 | }
81 | ```
82 |
83 |
84 |
85 | ### Transaction signature
86 |
87 | TxData calculates the hash value of transaction data through the Keccak-256 algorithm, and then combines the private key of the account to generate signature data through ECDSA (Elliptic Curve Digital Signature Algorithm), which is the elliptic curve digital signature algorithm.
88 |
89 | Of course, we can also send the private key to others for direct verification. But in this case, our account has no security at all. Once the private key is exposed, our account balance will be quickly removed.
90 |
91 |
92 |
93 | #### Keccak-256
94 |
95 | Keccak-256 algorithm is a hash function defined in the SHA-3 standard, which is a member of the Keccak hash function family designed by Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche. The algorithm is based on the Keccak-f permutation function and uses the SPONGE construction method to compute the hash of any input data with a fixed output length of 256 bits.
96 |
97 | The specific steps of the Keccak-256 algorithm are as follows:
98 |
99 | 1. Padding the data
100 |
101 | First, the input data is padded to a length that is a multiple of 136 bytes. The padding rules are as follows:
102 |
103 | - Append a binary 1 to the end of the data.
104 | - Append several binary 0s to the end of the data to make the length a multiple of 136 bytes.
105 | - Append a 32-bit binary integer to the end of the padded data to represent the length of the original data (in bits).
106 |
107 | 1. Computing the hash
108 |
109 | Divide the padded data into several 136-byte blocks and compute the hash of each block. The hash calculation process includes the following steps:
110 |
111 | - Divide each block into 17 8-byte slices called "states".
112 | - Perform a series of permutation operations on the states, called the Keccak-f permutation function.
113 | - Repeat the permutation operation on each block until all blocks have been processed.
114 |
115 | 1. Output the hash value
116 |
117 | The state of the last block is used as the output hash value.
118 |
119 | The Keccak-256 algorithm is relatively simple, but it uses advanced techniques to enhance security, making it effective against various attacks.
120 |
121 |
122 |
123 | ### ECDSA
124 |
125 |
126 |
127 | Then let's see how this value pair is created for signing:
128 |
129 | 1. generate a random number k
130 | 2. Calculate using dot multiplication p = k * G
131 | 3. R = xP, hash of txData is z
132 | 4. mod p
133 |
134 |
135 |
136 | So, the sender should send R, S, PubKey, in header, and txData in Body.
137 |
138 | The receiver can check if the sign is correct.
139 |
140 | The receiver just do this.
141 |
142 | P = S ^ -1 * z * G + S^-1 * R * PubKey
143 |
144 | if xP = R, the data is correct. In this way, a verification is completed without exposing the private key.
145 |
146 | We can prove this.
147 |
148 | ```go
149 | P = S ^ -1 * z * G + S^-1 * R * PubKey
150 | //PubKey = privKey * G, so
151 | P = S ^ -1 * z * G + S^-1 * R * privKey * G
152 | P = S ^ -1 * z * G + S^-1 * R * privKey * G
153 | P = S ^ -1 * G * ( z + R * privKey)
154 | // if P is a point in ECC, there must be some K make P = K * G, so
155 | K * G = S ^ -1 * G * ( z + R * privKey)
156 | K = S ^ -1 * ( z + R * privKey)
157 |
158 |
159 | // And we know how sender create S.
160 | S = k ^ -1( z + privKey * R)
161 | k = S ^ -1 * ( z + R * privKey)
162 |
163 | So, k = K
164 | ```
165 |
166 |
167 |
168 | ### Questions
169 |
170 | - Can you explain the difference between on chain and off chain transactions in web3?
171 |
172 | - On-chain transactions refer to transactions that are recorded and executed directly on the blockchain. These transactions involve sending or receiving cryptocurrency or tokens, executing smart contracts, and updating the state of the blockchain. On-chain transactions require gas fees to be paid in order to incentivize miners to validate and process the transaction. Once a transaction is processed and confirmed by the network, it is permanently recorded on the blockchain and can be viewed by anyone.
173 |
174 | Off-chain transactions, on the other hand, refer to transactions that occur outside of the blockchain, but are still related to the blockchain. These transactions can include transferring cryptocurrency or tokens between two parties using an off-chain payment channel, such as the Lightning Network, which allows for instant and low-cost transactions. Off-chain transactions can also include any interactions between two or more parties that do not involve updating the state of the blockchain. Off-chain transactions do not require gas fees and can occur instantly without the need for confirmation by the network.
175 |
176 | In summary, on-chain transactions involve interacting directly with the blockchain and updating its state, while off-chain transactions occur outside of the blockchain and can involve various forms of payment channels or other interactions between parties. Both types of transactions have their advantages and disadvantages, and their suitability depends on the specific use case and requirements.
177 |
178 | - Can you "hide" a transaction in Ethereum?
179 |
180 | - In Ethereum, you cannot truly "hide" a transaction because Ethereum's transaction records are public and can be viewed by anyone. However, there are some techniques that can obscure the traceability of a transaction, making it more difficult to discover.
181 |
182 | One method is to use smart contracts to proxy the transaction. This method can hide the sender and receiver of the transaction behind the smart contract, making the transaction appear to be sent by the contract itself rather than the actual sender. However, this method still leaves a record of the contract transaction, so it is still traceable.
183 |
184 | Another method is to use cryptocurrency mixers. These services mix a user's cryptocurrency with other users' cryptocurrency to make it more difficult to trace the sender and receiver of each specific transaction. However, this method can still be traceable as the mixer service may leave some traces in the transaction.
185 |
186 | In summary, while transactions cannot truly be "hidden" in Ethereum, there are techniques that can be used to increase transaction privacy and security. However, it should be noted that these methods may not be entirely reliable and have some risks and vulnerabilities, so they should be used with caution.
187 |
188 | - What tools are needed to sign a transaction?
189 |
190 | - Private Key
191 |
--------------------------------------------------------------------------------
/ethereum/zero-knowledge-proof.md:
--------------------------------------------------------------------------------
1 | # Zero Knowledge Proof and zk-SNARK
2 |
3 | Here's the classic example given in every complexity course I've taken:
4 | Let's say your friend is colorblind.
5 |
6 | 1. You have two billiard balls; one is red and one is green, but they are otherwise identical.
7 | 2. To your friend they look identical and he doubts they can really be distinguished.
8 | 3. You want to prove to him that they are actually different colors.
9 | 4. On the other hand, you don't want him to know which is red and which is green.
10 |
11 | This is the proof system.
12 |
13 | 1. You give your friend two balls to hold one in each hand.
14 | 2. At this point you can see the ball, but you don't tell him which is which.
15 | 3. Then your friend puts his hands behind his back. Next, he either switches the balls between the hands or leaves them as they are, with probability 1/2 for each hand. Finally, he brought them out from behind.
16 | 4. You now have to "guess" if he switched the ball.
17 |
18 | You can of course say for sure if he replaced them by looking at their color.
19 | On the other hand, if they are the same color and are therefore indistinguishable, then it is impossible for you to guess correctly with a probability higher than 1/2.
20 |
21 | If you and your friend repeat this "proof" 10000 times, your friend should be confident that the balls are indeed different colors; otherwise, your probability of successfully identifying all switches/non-switches is at most 2^(−10000).
22 |
23 | Also, the proof is "zero-knowledge" because your friend will never know which ball is green and which is red;
24 | In fact, he knew nothing about how to distinguish the balls.
25 |
26 |
27 |
28 | ### zk-SNARK
29 |
30 | Around 2013, ZK-SNARKs (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge), an algorithm for constructing digital signatures based on interactive zero-knowledge proofs, was practically feasible and implemented, and actually used in applications.
31 |
32 |
33 |
34 | Zcash is the first widespread application of zk-SNARKs, a novel form of zero-knowledge cryptography. Zcash's strong privacy guarantees stem from the fact that shielded transactions in Zcash can be fully encrypted on the blockchain, yet still verifiable under the network's consensus rules by using zk-SNARK proofs.
35 |
36 | The acronym zk-SNARK stands for "Zero-Knowledge Succinct Non-Interactive Argument of Knowledge" and refers to a proof structure in which one can prove possession of certain information, such as a secret key, while There is no need to reveal that information, and there is no interaction between prover and verifier.
37 |
38 |
39 |
40 | Zcash is the first widespread application of zk-SNARKs. Zcash's strong privacy guarantees stem from the fact that shielded transactions in Zcash can be fully encrypted on the blockchain, yet still verifiable under the network's consensus rules by using zk-SNARK proofs.
41 |
42 | **One can prove possession of certain information, such as a private key, without revealing that information, and without any interaction between the prover and the verifier.**
43 |
44 | "Zero-knowledge" proofs allow one party (the prover) to prove to another party (the verifier) that a statement is true without revealing any information beyond the validity of the statement itself. For example, given a hash of a random number, a prover can convince a verifier that there is indeed a number with that hash value, and that the prover really knows that number, without revealing what it is.
45 |
46 | "Succinct" zero-knowledge proofs can be verified in milliseconds, even for statements about very large programs, and the proof length is only a few hundred bytes. In a "non-interactive" structure, a proof consists of a single message sent from the prover to the verifier.
47 |
48 | Define V to represent the verifier, P to represent the prover, F(x), M(x) are polynomial functions, and the highest order is K
49 |
50 |
51 |
52 | ##### Polynomial Zero Problem
53 |
54 | Suppose V has a function F(x) and P has a function M(x). P tries to prove that P knows F(x), ie M(x) = F(x)
55 |
56 | Then first, P asks V to give it a random number a, and then P returns the value of M(a) to V.
57 |
58 | V calculates F(a) == M(a).
59 |
60 | This is because the zeros of the polynomial are finite and at most the order K of the equation. If M(x) recognized by P is not F(x). Then g(x) = F(x) - M(x) with only not many and K zeros. V is a value a randomly selected within the range of real numbers, which just satisfies g(a), and the probability of wrong judgment of V is extremely low.
61 |
62 | In fact, V can repeat this operation 100 times. If these 100 P times give correct results, it is almost certain that P really knows F(x), that is, M(x) = F(x).
63 |
64 | If P really doesn't know F(x), it is guessing, and the difficulty of guessing will even increase rapidly with the increase of K.
65 |
66 |
67 |
68 | ##### Digital Encryption
69 |
70 | Choose a base number, such as 5, if we want to encrypt 3, the encryption method is 5^3= 125
71 |
72 | Define the encryption function as E(v) = g^v mod n, where v is the number we need to encrypt. Obviously, if one obtains E(a) in a transmission, it is almost impossible for that person to deduce what a actually is.
73 |
74 | What are the advantages of this function?
75 |
76 |
77 |
78 | Suppose V knows F(x) = x^3 + x^2 + x, which can be expressed as (1, 1, 0 ) base g.
79 |
80 | P tries to prove that he knows the equation.
81 |
82 | Then V generates a random number a, and will send a set of numbers to P A0 = ga, A1 = ga2, A2 = g< sup>a3
83 |
84 | P performs the following operations.
85 |
86 | result = A0 * A1 * A2 = ga * ga2 * ga3 = ga3+ a2+a
87 |
88 | P just send the result back.
89 |
90 |
91 |
92 | After V receives the result and knows g and a, he can quickly verify the result.
93 |
94 |
95 |
96 | In this process,
97 |
98 | V did not expose g, a.
99 |
100 | It is difficult for P to guess the result without knowing F(x).
101 |
102 |
103 |
104 | ##### Restricting a Polynomial
105 |
106 | Notice!
107 |
108 | As V, our real expectation is that P use the A0 = ga sent by me, A1 = ga2, A2 = ga3, with polynomial coefficients for calculation.
109 |
110 | But if there is a fake FP, it can hold the coefficient of g (initiate a random request first), such as B0 = gb, B1 = gb2, B2 = gb3
111 |
112 | Then use these numbers to violently piece together the result.
113 |
114 |
115 |
116 | To solve this problem, we introduce Knowledge-of-Exponent Assumption” (KEA)
117 |
118 | V first generates a random number r and an offset a, and sends two sets of data to P.
119 |
120 | A0 = gr, A1 = gr2, A2 = gr3
121 |
122 | B0 = gar, B1 = gar2, B2 = gar3
123 |
124 |
125 |
126 | P must count the two groups at the same time.
127 |
128 |
129 |
130 | So far, we have solved zero-knowledge. Obviously, it is completely impossible for P to gain any knowledge from the data given by V.
131 |
132 | Why do we even need to have non-interactive?
133 |
134 | Because the interactive proof is only valid for the original verifier V, no one else (other verifiers) can trust this proof,
135 |
136 | Obviously, V can tell P about r and a. P can happily generate these fake data. The other V's certainly can't trust P's credibility.
137 |
138 | Instead, each V requires P to interact with itself.
139 |
140 |
141 |
142 | Use the elliptic curve to realize the following function, which satisfies the definition
143 |
144 | e(ga , gb ) = e(gb , ga ) = e(gab, g1 ) = e(g1 ,gab)) = e(g1 , ga )b = e(g1 , g1 ) ab
145 |
146 |
147 |
148 | We let an honest party generate secret values r and α. Once α and all necessary powers of r and their corresponding α offsets are generated and encrypted, the original data must be deleted. Call it common reference string or CRS
149 |
150 | (ga, gri , gari , r = 0 1,..., d ).
151 |
152 |
153 |
154 | Among them, V needs to send gri , gari to P.
155 |
156 | P returns the calculation result to V according to the function coefficients it knows.
157 |
158 | V uses (ga, gri ) verification.
159 |
160 |
161 |
162 | Of course, if all nodes generate r and a continuously in the actual environment, this is the setup process.
163 |
164 | Generally speaking, we don't need to prove "whether someone knows a polynomial", but "whether someone knows a secret value, which satisfies certain conditions (such as the hash value x)". So how to turn the problem of "does someone know a secret value, which satisfies certain conditions" into a question of "does someone know a polynomial"?
165 |
166 | We can write a program to check whether this value satisfies the condition. If it is satisfied, it will output 1, and if it is not satisfied, it will output 0. And through some methods that people have developed, the program can be converted into a circuit, and the input and output of the circuit are the program. Input-Output (P(x) = A(x)B(x)-C(x)). And the circuit can be converted into a polynomial with a specific zero root (the coefficients of the polynomial are related to each input and output of the circuit).
167 |
168 |
169 |
170 | ### ZK Rollups
171 |
172 | Rollup is a scaling solution that executes transactions outside L1 but publishes transaction data on L1. This way of working allows rollups to expand the network while still being securely protected by the Ethereum consensus. Moving computation off-chain can actually process more transactions. Because only some data of the rollup transaction needs to be put into the Ethereum block.
173 |
174 | After executing the transactions on the rollup, the next step is to package these transactions into a batch and publish it to the Ethereum main chain. The whole process is basically executing transactions, extracting data, compressing them, rolling them into batches and sending them to the main chain, hence the name - "rollup".
175 |
176 | How does Ethereum know that this data is valid and not submitted by malicious actors for profit? Each rollup deploys a set of smart contracts in L1 to process deposits, withdrawals, and verify proofs. Proof is also the main factor that differentiates the different types of rollups.
177 |
178 |
179 | In ZK rollups, each batch published to L1 contains a cryptographic proof called a ZK-SNARK. After the transaction batch is submitted to L1, the contract on L1 can quickly verify the ZK-SNARK proof, and invalid batches will be directly rejected.
180 |
--------------------------------------------------------------------------------
/ethereum/evm.md:
--------------------------------------------------------------------------------
1 | # EVM
2 |
3 | Usually, the development process of a smart contract is to use solidity to write logic code, compile it into bytecode through a compiler, and then publish it on Ethereum. The bottom layer of Ethereum supports the execution and calling of contracts through the EVM module. When calling, the code is obtained according to the contract address, that is, The bytecode of the contract is loaded into the EVM for execution after the environment is generated.
4 |
5 | The general flow is as shown in Figure 1. The execution process of the instructions is shown in Figure 2. The instructions are continuously fetched from the EVM code for execution, using Gas to realize the limit cycle, using the stack for operations, storing temporary variables in the memory, and storing data in the account state. .
6 |
7 | EVM distinguishes between temporary storage (Memory, which exists in each VM instance and disappears after the execution of the VM) and permanent storage (Storage, which exists in the state layer of the blockchain).
8 |
9 |
10 |
11 | 
12 |
13 |
14 |
15 | 
16 |
17 |
18 |
19 |
20 |
21 | ### Code
22 |
23 | ```go
24 | type Context struct {
25 | CanTransfer CanTransferFunc
26 | Transfer TransferFunc
27 | GetHash GetHashFunc
28 | Origin common.Address
29 | GasPrice *big.Int
30 | Coinbase common.Address
31 | GasLimit uint64
32 | BlockNumber *big.Int
33 | Time *big.Int
34 | Difficulty *big.Int
35 | }
36 |
37 | type EVM struct {
38 | Context
39 | StateDB StateDB
40 | depth int
41 | chainConfig *params.ChainConfig
42 | chainRules params.Rules
43 | vmConfig Config
44 | interpreter *Interpreter
45 | abort int32
46 | callGasTemp uint64
47 | }
48 |
49 | // create Contract
50 | func (evm *EVM) create(caller ContractRef, code []byte, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) {
51 | if evm.depth > int(params.CallCreateDepth) { // less then 1024
52 | return nil, common.Address{}, gas, ErrDepth
53 | }
54 | if !evm.CanTransfer(evm.StateDB, caller.Address(), value) { // Check account balance
55 | return nil, common.Address{}, gas, ErrInsufficientBalance
56 | }
57 | nonce := evm.StateDB.GetNonce(caller.Address())
58 | evm.StateDB.SetNonce(caller.Address(), nonce+1)
59 |
60 | contractHash := evm.StateDB.GetCodeHash(address)
61 | if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) {
62 | return nil, common.Address{}, 0, ErrContractAddressCollision
63 | }
64 |
65 | snapshot := evm.StateDB.Snapshot()
66 | evm.StateDB.CreateAccount(address)
67 | if evm.ChainConfig().IsEIP158(evm.BlockNumber) {
68 | evm.StateDB.SetNonce(address, 1)
69 | }
70 | evm.Transfer(evm.StateDB, caller.Address(), address, value)
71 |
72 | contract := NewContract(caller, AccountRef(address), value, gas)
73 | contract.SetCallCode(&address, crypto.Keccak256Hash(code), code)
74 |
75 | if evm.vmConfig.NoRecursion && evm.depth > 0 {
76 | return nil, address, gas, nil
77 | }
78 |
79 | if evm.vmConfig.Debug && evm.depth == 0 {
80 | evm.vmConfig.Tracer.CaptureStart(caller.Address(), address, true, code, gas, value)
81 | }
82 | start := time.Now()
83 |
84 | ret, err := run(evm, contract, nil)
85 |
86 | maxCodeSizeExceeded := evm.ChainConfig().IsEIP158(evm.BlockNumber) && len(ret) > params.MaxCodeSize
87 |
88 | if err == nil && !maxCodeSizeExceeded {
89 | createDataGas := uint64(len(ret)) * params.CreateDataGas
90 | if contract.UseGas(createDataGas) {
91 | evm.StateDB.SetCode(address, ret)
92 | } else {
93 | err = ErrCodeStoreOutOfGas
94 | }
95 | }
96 |
97 | if maxCodeSizeExceeded || (err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) {
98 | evm.StateDB.RevertToSnapshot(snapshot)
99 | if err != errExecutionReverted {
100 | contract.UseGas(contract.Gas)
101 | }
102 | }
103 |
104 | if maxCodeSizeExceeded && err == nil {
105 | err = errMaxCodeSizeExceeded
106 | }
107 | if evm.vmConfig.Debug && evm.depth == 0 {
108 | evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
109 | }
110 | return ret, address, contract.Gas, err
111 |
112 | }
113 | ```
114 |
115 |
116 |
117 | First, a series of verifications will be performed,
118 |
119 | 1. The depth of the call stack cannot exceed 1024;
120 | 2. The called account has enough balance;
121 | 3. Initiate a transfer operation, subtract the value from the sender’s address balance, add the value to the balance of the contract account, and then call SetCallCode of the contract to initialize the contract according to the sender’s address, contract address, amount value, gas, contract code, and code hash Object, and then call run(evm, contract, nil) to execute the initialization code of the contract. The generated code has a certain length limit. When the contract is successfully created and no error is returned, the gas required to store the code is calculated.
122 |
123 | It can be seen that the contract code is stored in the storage area pointed to by the codehash in the account through the SetCode of the state module. This part of the code belongs to the modification of the world state.
124 |
125 | The fund transfer of the Create method occurs between the creating contract user account and the contract account
126 |
127 |
128 |
129 | ### Call
130 |
131 | When transferring money or executing contract code, the Call method will be called, and the call instruction in the contract will also call this method.
132 |
133 |
134 |
135 | ```go
136 | func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
137 | if evm.vmConfig.NoRecursion && evm.depth > 0 {
138 | return nil, gas, nil
139 | }
140 |
141 | if evm.depth > int(params.CallCreateDepth) {
142 | return nil, gas, ErrDepth
143 | }
144 | if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
145 | return nil, gas, ErrInsufficientBalance
146 | }
147 |
148 | var (
149 | to = AccountRef(addr)
150 | snapshot = evm.StateDB.Snapshot()
151 | )
152 | if !evm.StateDB.Exist(addr) {
153 | precompiles := PrecompiledContractsHomestead
154 | if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
155 | precompiles = PrecompiledContractsByzantium
156 | }
157 | if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
158 | if evm.vmConfig.Debug && evm.depth == 0 {
159 | evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
160 | evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil)
161 | }
162 | return nil, gas, nil
163 | }
164 | evm.StateDB.CreateAccount(addr)
165 | }
166 | evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
167 |
168 | contract := NewContract(caller, to, value, gas)
169 | contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
170 |
171 | start := time.Now()
172 |
173 | if evm.vmConfig.Debug && evm.depth == 0 {
174 | evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
175 |
176 | defer func() {
177 | evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
178 | }()
179 | }
180 | ret, err = run(evm, contract, input) // run the code for smart contract
181 |
182 | if err != nil {
183 | evm.StateDB.RevertToSnapshot(snapshot)
184 | if err != errExecutionReverted {
185 | contract.UseGas(contract.Gas)
186 | }
187 | }
188 | return ret, contract.Gas, err
189 | }
190 |
191 | func run(evm *EVM, contract *Contract, input []byte) ([]byte, error) { //The Run method will execute the code of the contract in a loop,
192 | if contract.CodeAddr != nil {
193 | precompiles := PrecompiledContractsHomestead
194 | if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
195 | precompiles = PrecompiledContractsByzantium
196 | }
197 | if p := precompiles[*contract.CodeAddr]; p != nil {
198 | return RunPrecompiledContract(p, input, contract)
199 | }
200 | }
201 | return evm.interpreter.Run(contract, input)
202 | }
203 | ```
204 |
205 |
206 |
207 | ### Gas for execute a call
208 |
209 | In order to optimize the execution efficiency of smart contracts and reduce Gas costs, the following measures can be taken:
210 |
211 | 1. Simplify the logic and code of smart contracts and reduce the computing resources required for execution.
212 |
213 | 2. Use Solidity to write efficient smart contract code, such as using appropriate data types and algorithms, and avoiding expensive operations such as loops and recursion.
214 |
215 | 3.
216 | Reduce the number of smart contract interactions and avoid frequent calls to other smart contracts and external services, thereby reducing the gas cost of the interaction.
217 |
218 | 4. Use Gas optimization tools, such as Solidity's gas() function, Remix, etc., to analyze the Gas consumption of smart contracts and further optimize the smart contract code.
219 |
220 |
221 |
222 | ### Questions
223 |
224 | - What are the components of the Ethereum Virtual Machine? What are the parts of the memory of the Ethereum virtual machine?
225 | - Stack: The stack is a data structure that stores values during the execution of a program. The EVM uses a stack-based architecture, which means that all operations are performed on the stack.
226 | - Memory: The memory is a linear array of bytes that can be used by a program to store data during execution. The memory is volatile, which means that it is cleared when the program terminates.
227 | - Storage: The storage is a persistent key-value store that is used to store data between transactions. The storage is backed by the blockchain, which means that it is immutable.
228 | - Please explain Storage, which variables are stored? .
229 | - Storage is a persistent key-value store that is used to store data between transactions. Variables that are stored in storage are persistent across multiple executions of a smart contract. In Solidity, variables declared with the "storage" keyword are stored in storage.
230 | - Please explain the memory (Memory), which variables are stored?
231 | - Memory is a linear array of bytes that can be used by a program to store data during execution. Unlike storage, the memory is volatile, which means that it is cleared when the program terminates. Variables that are stored in memory are not persistent across multiple executions of a smart contract. In Solidity, variables declared with the "memory" keyword are stored in memory.
232 | - Please explain Calldata.
233 | - Calldata is a read-only area of memory that contains the input data for a function call. When a function is called in a smart contract, the input data is passed to the function via the calldata. The calldata is immutable, which means that it cannot be modified by the function.
234 | - What is the difference between EVM calls and non-EVM calls?
235 | - EVM calls are function calls that are executed within the Ethereum Virtual Machine. EVM calls are used to call functions within a smart contract or to call other smart contracts. Non-EVM calls are function calls that are executed outside of the Ethereum Virtual Machine. Non-EVM calls are used to interact with external systems, such as APIs or databases. EVM calls are more expensive than non-EVM calls because they require more computation and are executed within the context of the Ethereum blockchain.
--------------------------------------------------------------------------------
/ethereum/mining-chainconfig.md:
--------------------------------------------------------------------------------
1 | # Mining:ChainConfig
2 |
3 | Mining is the process of encapsulating a series of recent unencapsulated transactions into a new block.
4 |
5 | Let us start with some context.
6 |
7 |
8 |
9 | ### Byzantine generals problem
10 |
11 | The state synchronization problem of distributed systems. Each node in a distributed system is a general, and when these nodes want to synchronize their state, they will face the Byzantine general problem.
12 |
13 | > The Byzantine Empire was prosperous, and the generals of several small countries around it coveted it for a long time, but each had their own secrets. More than half of their generals must agree to attack Byzantium and cannot betray on the battlefield (reach a consensus), otherwise the attack will fail and burn themselves. And the general's territory may be divided up by several other generals. Based on this situation, the communication among the generals is very problematic. Some people have duplicity, and some people are loyal to the interests of the organization. How to finally reach a consensus is a problem.
14 |
15 | #### POW(Proof Of Work)
16 |
17 | In order to solve the Byzantine general problem, we need to determine a method first:
18 |
19 | Select a loyal "general" from among these equal generals, and the other generals can just listen to his decision.
20 |
21 | > This seems to violate the idea of decentralization, but after careful analysis, these generals are decentralized equal nodes before making this decision, and the selected generals are only for this decision. Decided to choose again. Instead of a centralized and permanently fixed general.
22 |
23 | How to choose a general?
24 | These generals are equal nodes, so we asked them to give a statement on this decision. Generals need to calculate based on known battlefield information, try to draw conclusions (blocks), and then broadcast the conclusions to other generals. If his conclusions are recognized by most generals, then he is the general of this round.
25 | At the same time, the general must always monitor the broadcast content from other generals. Once the conclusion broadcast from other generals is received, the generals will immediately stop the calculations in their hands to verify the content of the broadcast. If all the generals pass the verification, then the first The first general who broadcasts this verifiable result is selected as a general, and this time he decided to listen to his conclusion.
26 |
27 | So there are two important factors in this process:
28 |
29 | 1. The first is speed, the first one who passes the verification can be selected as a general, and the second one who is a step slower has no chance. The problem of speed is the problem of computing power. For example, the computing power of an 8-core 32G computer is definitely faster than that of a single-core 1G.
30 |
31 | 2. Then there is correctness, that is, whether the conclusion issued by the general is correct or not, and needs to be verified successfully by other generals.
32 |
33 | POW provides a way that is difficult to calculate and easy to verify, which is realized based on the characteristics of the hash function.
34 |
35 | A hash encryption function can be issued to each node, and each node calculates an encrypted hash by adding a nonce value to the block information to be sealed. This encrypted hash needs to meet certain rules (such as the first four bits must be 1111)
36 | The workload refers to the workload that the node is constantly trying to calculate. After obtaining the eligible block hash, after broadcasting, the ongoing and completed workload of other nodes will be invalidated (in fact, this is also a kind of computing power. waste), this is the block.
37 |
38 |
39 |
40 | This way is not prefect.
41 |
42 | ##### Question 1:
43 |
44 | What if two nodes produce blocks with the same content at the same time?
45 |
46 | Compare timestamps. The one with an earlier time will be confirmed and kept on-chain, while the one with a later time will be discarded.
47 |
48 | ##### Question 2: Fork
49 |
50 | If a node publishes a new consensus rule, other nodes do not synchronize the consensus rule?
51 | Nodes that have not synchronized the new rules will continue to mine, and the blocks they dig will not be consensus or recognized by the nodes of the new rules. At this time, the chain is forked and divided into two chains, 1.0 (old consensus rules) and 2.0 (new consensus rules). At this point chains with a larger mass (miner) base will stay.
52 |
53 | Of course, some people still use the original 1.0 chain, but its vitality is definitely gone, because **no one will do it for nothing**.
54 |
55 |
56 |
57 | ### Source code for Miner
58 |
59 | Here is the UML for mining.
60 |
61 | 
62 |
63 | Here is the code.
64 |
65 | ```go
66 | type Miner struct {
67 | mux *event.TypeMux // Mux
68 | worker *worker
69 | coinbase common.Address
70 | mining int32 // mining status
71 | eth Backend // Backend
72 | engine consensus.Engine //ethash, clique。
73 | canStart int32 // Can i start mining?
74 | shouldStart int32 // Should i start mining after block sync?
75 | }
76 |
77 | type worker struct {
78 | config *params.ChainConfig
79 | engine consensus.Engine
80 |
81 | mu sync.Mutex
82 |
83 | // update loop
84 | mux *event.TypeMux
85 | txCh chan core.TxPreEvent
86 | txSub event.Subscription
87 | chainHeadCh chan core.ChainHeadEvent
88 | chainHeadSub event.Subscription
89 | chainSideCh chan core.ChainSideEvent
90 | chainSideSub event.Subscription
91 | wg sync.WaitGroup
92 |
93 | agents map[Agent]struct{} // worker have a map for Agents
94 | recv chan *Result
95 |
96 | eth Backend
97 | chain *core.BlockChain
98 | proc core.Validator
99 | chainDb ethdb.Database
100 |
101 | coinbase common.Address
102 | extra []byte
103 |
104 | currentMu sync.Mutex
105 | current *Work
106 |
107 | uncleMu sync.Mutex
108 | possibleUncles map[common.Hash]*types.Block
109 |
110 | unconfirmed *unconfirmedBlocks // 本地挖出的待确认的块
111 |
112 | mining int32
113 | atWork int32
114 | }
115 |
116 | // ChainConfig is the core config which determines the blockchain settings.
117 | //
118 | // ChainConfig is stored in the database on a per block basis. This means
119 | // that any network, identified by its genesis block, can have its own
120 | // set of configuration options.
121 | type ChainConfig struct {
122 | ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection
123 |
124 | HomesteadBlock *big.Int `json:"homesteadBlock,omitempty"` // Homestead switch block (nil = no fork, 0 = already homestead)
125 |
126 | DAOForkBlock *big.Int `json:"daoForkBlock,omitempty"` // TheDAO hard-fork switch block (nil = no fork)
127 | DAOForkSupport bool `json:"daoForkSupport,omitempty"` // Whether the nodes supports or opposes the DAO hard-fork
128 |
129 | // EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
130 | EIP150Block *big.Int `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork)
131 | EIP150Hash common.Hash `json:"eip150Hash,omitempty"` // EIP150 HF hash (needed for header only clients as only gas pricing changed)
132 |
133 | EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block
134 | EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block
135 |
136 | ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium)
137 | ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated)
138 | PetersburgBlock *big.Int `json:"petersburgBlock,omitempty"` // Petersburg switch block (nil = same as Constantinople)
139 | IstanbulBlock *big.Int `json:"istanbulBlock,omitempty"` // Istanbul switch block (nil = no fork, 0 = already on istanbul)
140 | MuirGlacierBlock *big.Int `json:"muirGlacierBlock,omitempty"` // Eip-2384 (bomb delay) switch block (nil = no fork, 0 = already activated)
141 | BerlinBlock *big.Int `json:"berlinBlock,omitempty"` // Berlin switch block (nil = no fork, 0 = already on berlin)
142 | LondonBlock *big.Int `json:"londonBlock,omitempty"` // London switch block (nil = no fork, 0 = already on london)
143 | ArrowGlacierBlock *big.Int `json:"arrowGlacierBlock,omitempty"` // Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated)
144 | GrayGlacierBlock *big.Int `json:"grayGlacierBlock,omitempty"` // Eip-5133 (bomb delay) switch block (nil = no fork, 0 = already activated)
145 | MergeNetsplitBlock *big.Int `json:"mergeNetsplitBlock,omitempty"` // Virtual fork after The Merge to use as a network splitter
146 |
147 | // Fork scheduling was switched from blocks to timestamps here
148 |
149 | ShanghaiTime *uint64 `json:"shanghaiTime,omitempty"` // Shanghai switch time (nil = no fork, 0 = already on shanghai)
150 | CancunTime *uint64 `json:"cancunTime,omitempty"` // Cancun switch time (nil = no fork, 0 = already on cancun)
151 | PragueTime *uint64 `json:"pragueTime,omitempty"` // Prague switch time (nil = no fork, 0 = already on prague)
152 |
153 | // TerminalTotalDifficulty is the amount of total difficulty reached by
154 | // the network that triggers the consensus upgrade.
155 | TerminalTotalDifficulty *big.Int `json:"terminalTotalDifficulty,omitempty"`
156 |
157 | // TerminalTotalDifficultyPassed is a flag specifying that the network already
158 | // passed the terminal total difficulty. Its purpose is to disable legacy sync
159 | // even without having seen the TTD locally (safer long term).
160 | TerminalTotalDifficultyPassed bool `json:"terminalTotalDifficultyPassed,omitempty"`
161 |
162 | // Various consensus engines
163 | Ethash *EthashConfig `json:"ethash,omitempty"`
164 | Clique *CliqueConfig `json:"clique,omitempty"`
165 | }
166 | ```
167 |
168 |
169 |
170 | We need to analyze ChainConfig, because this configuration is very important, and we can trace the update of Ethereum through this configuration.
171 |
172 |
173 |
174 | ### ChainID
175 |
176 | The ChainID of Ethereum is an identifier used to differentiate between different Ethereum networks and prevent accidental interactions between them. In the Ethereum network, each block contains a ChainID field that specifies which network the block belongs to.
177 |
178 | In Ethereum, replay protection is a mechanism used to prevent transactions from being executed repeatedly across different networks. Replay protection is achieved by using network-specific transaction formats that include the ChainID field. When a transaction is sent to the network, nodes check whether the ChainID field in the transaction matches the ChainID of the network. If it doesn't match, the transaction is rejected.
179 |
180 | For example, when an Ethereum network forks, the new fork may use a different ChainID. If a user sends a transaction on the old network before the fork, that transaction may be replayed on the new fork by malicious nodes, resulting in unexpected loss of funds. By using ChainID to differentiate between networks and using network-specific transaction formats to protect against replay, this risk can be avoided.
181 |
182 | The exact number of ChainIDs may change over time due to network upgrades and forks. Here are some examples of ChainIDs for different Ethereum networks:
183 |
184 | - Mainnet: 1
185 | - Ropsten testnet: 3
186 | - Rinkeby testnet: 4
187 | - Kovan testnet: 42
188 | - Goerli testnet: 5
189 | - Ethereum Classic mainnet: 61
190 |
191 |
192 |
193 | ### HomesteadBlock
194 |
195 | The Homestead upgrade was planned as the first hard fork of the Ethereum network, implemented on March 14, 2016 at block 1,150,000. The Homestead upgrade mainly includes three important improvements to Ethereum. First, it removes the canary contract, removing the centralized part of the network. Second, it introduces new code in Solidity, Ethereum’s contract programming language. Finally, it introduces the Mist wallet, which allows users to hold/trade ETH and write/deploy smart contracts.
196 |
197 | The Homestead upgrade was one of the first Ethereum Improvement Proposals (EIPs) to be implemented.
198 |
199 | When the HomesteadBlock attribute is specified in ChainConfig, the Ethereum node will enable the Homestead upgrade after the specified block height. This helps ensure that all nodes on the Ethereum network implement the Homestead upgrade at the same block height and correctly handle the new opcodes and exception handling mechanisms.
200 |
201 |
202 |
203 | ### DAOForkBlock
204 |
205 | On the Ethereum blockchain, DAO (Decentralized Autonomous Organization) was a self-governing decentralized organization aimed at creating a decentralized investment fund through smart contracts. In 2016, DAO suffered a hack that resulted in over 3 million ether being stolen. To prevent further losses, the Ethereum community decided to perform a hard fork to roll back the transaction, which is known as the DAO fork.
206 |
207 | DAOForkBlock is an attribute in the Ethereum ChainConfig that defines the block height of the DAO fork on the Ethereum blockchain. Its purpose is to specify the time at which the DAO fork will take effect in the Ethereum software code.
208 |
209 | Specifically, if the DAO fork block height of an Ethereum node is lower than the DAOForkBlock attribute specified block height, then that node will follow the DAO smart contract. Otherwise, it will execute the new chain after the DAO fork. Therefore, the DAOForkBlock attribute is an important parameter in the Ethereum software that ensures the stability and security of the Ethereum blockchain.
210 |
211 |
212 |
213 | ### EIP150Block
214 |
215 | The purpose of the EIP150Block attribute is to ensure that Ethereum nodes can promptly apply the protocol changes specified by EIP-150 once the specified block height is reached, in order to improve the security and performance of the Ethereum network.
216 |
217 | Specifically, the changes introduced by EIP-150 include:
218 |
219 | 1. Adopting a more secure ECDSA signature algorithm (replacing the previous use of SECP256k1);
220 | 2. Modifying the miner reward mechanism, reducing block rewards and increasing the proportion of miner fees;
221 | 3. Modifying the state transition function to eliminate some potential security vulnerabilities.
222 |
223 |
224 |
225 | ### EIP155Block
226 |
227 | Before the implementation of the EIP-155 specification, Ethereum and Ethereum Classic (ETC) shared the same network ID and chain ID for a period of time, which caused confusion with transactions being replayed on both networks. The implementation of the EIP-155 specification resolved this issue, but it needed to take effect after a specific block height. Therefore, the EIP155Block property is used to specify the block height at which the EIP-155 specification was implemented on the Ethereum network.
228 |
229 |
230 |
231 | ### ByzantiumBlock
232 |
233 | After the Byzantium hard fork, the Ethereum network introduced some new features and improvements, including faster block confirmation times, better privacy and security, and better smart contract programming capabilities. These improvements require protocol upgrades to be implemented, so it is necessary to specify the ByzantiumBlock property to ensure that nodes on the network have already been upgraded.
234 |
235 |
236 | ### ShanghaiTime
237 |
238 | Ethereum nodes use the ShanghaiTime property to calculate the timestamps of blocks, ensuring that the timestamps in the blockchain are accurate and consistent with Shanghai time. This can be important for certain blockchain applications and smart contracts that need to determine the exact time something happened, such as in time-sensitive transactions that require proof of certain events.
239 |
--------------------------------------------------------------------------------
/ethereum/ethereum-account-state.md:
--------------------------------------------------------------------------------
1 | # Ethereum Account and State
2 |
3 | There are two account models in the blockchain world:
4 |
5 | 1. UTXO (Unspent Transaction Output) model
6 | 2. account balance model
7 |
8 |
9 |
10 | UTXO does not record the account balance, but only records each transaction, and the account balance is obtained by calculating all historical transactions of the account (imagine if you know every transaction in your wife/husband’s bank account transaction, then you can figure out how much money she/he has on the card now).
11 |
12 | The account balance model is similar to the bank accounts we often use, and they all save the balance of our account. When someone transfers money to us, we add the value of the balance to the value of the transfer; when we transfer money to someone else, we subtract the value of the transfer from the number of the balance.
13 |
14 | From this point of view, the account balance model is relatively easy to understand. Ethereum uses the account balance model, and it is the state module that implements this model. It records the status of each account, and changes the status of the corresponding account whenever a transaction occurs.
15 |
16 |
17 |
18 | ### Why does Ethereum use a balance model instead of a UTXO model?
19 |
20 | 1. Programmable transactions: Ethereum is a **smart contract** platform that allows users to write programmatic smart contracts on the blockchain. This means that transactions in Ethereum may involve multiple inputs and outputs, rather than just one input and one output like in Bitcoin. This complex transaction structure makes the UTXO model difficult to implement, while the balance model is better suited to support these complex transactions.
21 | 2. State storage: **Smart contracts** in Ethereum can modify the contract state, which needs to be stored on the blockchain. If a UTXO model is used, every state change would require the creation of new unspent transaction outputs, which would result in huge transaction volumes and high blockchain storage costs. The balance model only needs to update the balance of the contract address, making it more efficient.
22 | 3. Computational cost: The execution of **smart contracts** in Ethereum requires computational resources. If a UTXO model is used, since each transaction output has its own value, the outputs must be split and recombined during contract execution, resulting in additional computational costs. The balance model only needs to maintain the balance of each address, making it simpler and more efficient.
23 |
24 | In summary, Ethereum uses the balance model to better support programmable transactions, reduce state storage costs, and computational costs.
25 |
26 |
27 |
28 | ### State Context
29 |
30 | #### state definition
31 |
32 | The information of an account is a **state**, and Ethereum is a collection of all **states**. For example, the initial **state** is: {A has 10 yuan, B has 0 yuan}, then A initiates a transaction and gives B 2 yuan, and the **state** becomes {A has 8 yuan, B has 2 yuan}, the intermediate process It's a **state** transition.
33 |
34 | The actual initial **state** of Ethereum is the genesis block, which is transferred to a new state every time a new block is generated.
35 |
36 |
37 |
38 | #### state indication
39 |
40 | Ethereum uses root to represent **state**. Ethereum uses **Trie** to organize the **state**. Trie can be understood as a combination of dictionary tree and Merkle tree. It has a tree root root. With this root, you can access all **state** data, that is, the information of each account, so Use root to represent a state.
41 |
42 |
43 |
44 | #### get state
45 |
46 | There is a field Root in the block header, so if you find the block header, you can get the state of the blockchain.
47 |
48 |
49 |
50 | #### Where does the state exist
51 |
52 | **State** does not exist in blocks. The root is stored in the block header, which is just an address, and the **state** data cannot be found from the block.
53 |
54 | **State is just temporary data that can be regenerated. The genesis block is the initial state. After executing all the transactions in the first block, a new state is obtained,** and the root of this state is stored in the Root of the first block header. If there are all blocks, all transactions can be executed, and then the state in the latest block can be generated.
55 |
56 | The state is stored in an external database. The underlying database of Ethereum is LevelDB, where the blocks are stored and the status is also stored in it. But the state is a Trie, which cannot be directly stored in LevelDB.
57 |
58 | Note: Although we can obtain the information of all accounts by traversing and executing all transactions in all blocks, the existence of state allows us to quickly obtain the balance of an account without performing such time-consuming operations every time.
59 |
60 |
61 |
62 | ### StateDB
63 |
64 | StateDB is the main object in the state module. It records the information of each account, including balance (number of ether), nonce and other information.
65 |
66 | The process of **transactions** being collected into **blocks** by **miners** is the process of **miners** performing **state** **transitions**. Even if there is no **transaction**, **miners** can directly migrate the world state to a new state, such as digging out empty blocks.
67 |
68 | Even in the early days of Ethereum, when Ethereum was running for three months, the local folder storage of Ethereum clients ballooned to a staggering 10 to 40 GB. As of block height 9001290, an Ethereum archive node that retains all state needs to occupy 216 GB of space. If these states are all recorded on the blockchain, then this will be a nightmare.
69 |
70 | This will make micro-devices such as Internet of Things devices, personal notebooks, and mobile phones unable to use the Ethereum client, which will lead to a decrease in the number of network nodes and affect user usage. Therefore, these states are not directly stored on the blockchain, but these states are maintained in the Merkle prefix tree, and only the corresponding tree Root value is recorded on the blockchain. Use a simple database to maintain the persistent content of the tree, and the database used to maintain the mapping is called StateDB.
71 |
72 | There are 2 types of state.
73 |
74 | - World state
75 | - Account state
76 |
77 | The following information is stored in the account status
78 |
79 | 1. **nonce**: This value is equal to the number of transactions issued by this account, or the number of contracts created by this account (when this account has an associated code).
80 | 2. **balance**: Indicates the account balance of this account.
81 | 3. **storageRoot**: Indicates the hash value of the root node of the MPT tree that saves the account storage content.
82 | 4. **codeHash**: Indicates the EVM code hash value of the account. When this address receives a message call, these codes will be executed; it is different from other fields and cannot be changed after creation. If codeHash is empty, it means that the account is a simple external account with only nonce and balance.
83 |
84 | 
85 |
86 |
87 |
88 | As shown in the figure above, all account states are maintained through the account address as the key, and the Merkle tree maintained is the world state.
89 | All accounts also have a tree representing the stored data of this account, which is independent and unique.
90 |
91 | The account status (such as account balance) can be found from the world state tree through the account address. If it is a contract address, you can also continue to use storageRoot to find the corresponding contract information from the account storage data tree (such as: in the auction contract. product information).
92 |
93 |
94 |
95 | ### How to init StateDB
96 |
97 | StateDB has many uses:
98 |
99 | 1. Maintain a mapping from account state to world state.
100 | 2. Support modification, rollback, commit status.
101 | 3. Supports persistent state to the database.
102 | 4. Is the medium through which states enter and exit the Merkle tree.
103 |
104 |
105 |
106 | At first, we should init a stateDB instance.
107 |
108 | First, we need to tell StateDB which state we want to use. Therefore, StateRoot needs to be provided as the root of the Merkle tree to build the tree.
109 |
110 | **The value of StateRoot is equivalent to the data version number**, according to the version number, it can be clearly known which version of the state to use. Of course, the data content is not in the tree and needs to be read in a database. Therefore, stateRoot and db need to be provided when building State DB to complete the build.
111 |
112 |
113 |
114 | ```go
115 | db: = state.NewDatabase(levelDB)
116 | statedb, err := state.New(block.Root(), db)
117 |
118 | //core/state/statedb.go:92
119 | func New(root common.Hash, db Database) (*StateDB, error) {
120 | tr, err := db.OpenTrie(root)//①
121 | if err != nil {
122 | return nil, err
123 | }
124 | return &StateDB{
125 | db: db,//②
126 | trie: tr,
127 | stateObjects: make(map[common.Address]*stateObject),
128 | stateObjectsDirty: make(map[common.Address]struct{}),
129 | logs: make(map[common.Hash][]*types.Log),
130 | preimages: make(map[common.Hash][]byte),
131 | journal: newJournal(),
132 | }, nil
133 | }
134 |
135 | //core/state/statedb.go:59
136 | type StateDB struct {
137 | db Database
138 | trie Trie
139 | stateObjects map[common.Address]*stateObject
140 | stateObjectsDirty map[common.Address]struct{}
141 | dbErr error
142 | refund uint64
143 |
144 | thash, bhash common.Hash
145 | txIndex int
146 | logs map[common.Hash][]*types.Log
147 | logSize uint
148 |
149 | preimages map[common.Hash][]byte
150 | journal *journal // change log, can use this to revert change
151 | validRevisions []revision
152 | nextRevisionId int
153 | }
154 |
155 | // core/state/database.go:42
156 | type Database interface {
157 | OpenTrie(root common.Hash) (Trie, error) // Opens the top-level tree containing the world state for the specified state version (root).
158 | OpenStorageTrie(addrHash, root common.Hash) (Trie, error) // Open the account data storage tree of the specified state version (root) under the addrHash. addrHash is the account
159 | CopyTrie(Trie) Trie
160 | ContractCode(addrHash, codeHash common.Hash) ([]byte, error) // Get the contract of the addrHash, which must match the contract hash (codeHash)
161 | ContractCodeSize(addrHash, codeHash common.Hash) (int, error)
162 |
163 | // TrieDB retrieves the low level trie database used for data storage.
164 | TrieDB() *trie.Database
165 | }
166 | ```
167 |
168 | Currently, there are two types of DBs that implement the Database interface, odrDatabase used by light nodes, and cachingDB with cache used by normal nodes.
169 |
170 | Because **light nodes do not store data**, they need to obtain data by querying other nodes, and odrDatabase is the encapsulation of this data reading method.
171 |
172 | An ordinary node has a built-in levelDB. In order to improve read and write performance, it is encapsulated once with cachingDB.
173 |
174 |
175 |
176 | ### How to use StateDB to change state
177 |
178 | All states are based on accounts. Any data must belong to a certain account state, and the world state is only a tree to establish a safe mapping. Accessible data can be divided into the following types:
179 |
180 | 1. Access account basic properties: Balance, Nonce, Root, CodeHash
181 | 2. Read contract account code
182 | 3. Read the content stored in the contract account
183 |
184 | For example, when we try to obtain the balance of an account, we need to specify the account address from the world state tree Trie, and then read the account state.
185 |
186 |
187 |
188 | ```go
189 | db: = state.NewDatabase(levelDB)
190 | block = blockchain.CurrentBlock()
191 | statedb, err := state.New(block.Root(), db)
192 | balance := statedb.GetBalance(addr1)
193 |
194 | //core/state/statedb.go:207
195 | func (self *StateDB) GetBalance(addr common.Address) *big.Int {
196 | stateObject := self.getStateObject(addr)//①
197 | if stateObject != nil {
198 | return stateObject.Balance()//③
199 | }
200 | return common.Big0//②
201 | }
202 |
203 | // core/state/statedb.go:408
204 | func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) {
205 | if obj := self.stateObjects[addr]; obj != nil {//①
206 | if obj.deleted {
207 | return nil
208 | }
209 | return obj
210 | }
211 |
212 | enc, err := self.trie.TryGet(addr[:])//②
213 | if len(enc) == 0 {
214 | self.setError(err)
215 | return nil
216 | }
217 | var data Account
218 | if err := rlp.DecodeBytes(enc, &data); err != nil {//③
219 | log.Error("Failed to decode state object", "addr", addr, "err", err)
220 | return nil
221 | }
222 | obj := newObject(self, addr, data)//④
223 | self.setStateObject(obj)
224 | return obj
225 | }
226 |
227 | type stateObject struct {
228 | address common.Address/
229 | addrHash common.Hash
230 | data Account
231 | db *StateDB
232 |
233 | //../ 存储树,第一次访问时初始化
234 | code Code // contract bytecode, which gets set when code is loaded
235 | //...
236 | }
237 | type Account struct {
238 | Nonce uint64
239 | Balance *big.Int
240 | Root common.Hash // merkle root of the storage trie
241 | CodeHash []byte
242 | }
243 | ```
244 |
245 |
246 |
247 | ##### How to send ETH to another account?
248 |
249 | In Ethereum, A transfers 100 ETH to B, and actually completes two state modification operations in the current state:
250 |
251 | 1. A's account balance decreases by 100 ETH.
252 | 2. B's account balance increases by 100 ETH.
253 |
254 |
255 |
256 | ```go
257 | db: = state.NewDatabase(levelDB)
258 | block = blockchain.CurrentBlock()
259 | statedb, err := state.New(block.Root(), db)
260 |
261 | statedb.SubBalance(A,100 ETH)
262 | statedb.AddBalance(B,100 ETH)
263 | ```
264 |
265 |
266 |
267 | ### How to use StateDB to read contract?
268 |
269 | The biggest difference between contract accounts and ordinary accounts is that they have their own storage tree
270 |
271 | ```go
272 | // core/state/state_object.go:152
273 | func (c *stateObject) getTrie(db Database) Trie {
274 | if c.trie == nil {
275 | var err error
276 | c.trie, err = db.OpenStorageTrie(c.addrHash, c.data.Root)//①
277 | if err != nil {
278 | c.trie, _ = db.OpenStorageTrie(c.addrHash, common.Hash{})//②
279 | c.setError(fmt.Errorf("can't create storage trie: %v", err))
280 | }
281 | }
282 | return c.trie
283 | }
284 | ```
285 |
286 |
287 |
288 | ### How to set changes StateDB into a real DB?
289 |
290 | StateDB can be regarded as an in-memory database. State data is first modified in the in-memory database, and all calculations about the state are completed in memory. When the block is persisted, the update storage from the memory to the database is completed. This update is an incremental update, and only the modification involves the modified part.
291 |
292 | ```go
293 | // core/state/statedb.go:680
294 | func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error) {
295 | defer s.clearJournalAndRefund()
296 |
297 | for addr := range s.journal.dirties {//①⑧⑨⑩
298 | s.stateObjectsDirty[addr] = struct{}{}
299 | }
300 | for addr, stateObject := range s.stateObjects {//②
301 | _, isDirty := s.stateObjectsDirty[addr]
302 | switch {
303 | case stateObject.suicided || (isDirty && deleteEmptyObjects && stateObject.empty()):
304 | //③
305 | s.deleteStateObject(stateObject)
306 | case isDirty:
307 | if stateObject.code != nil && stateObject.dirtyCode {//④
308 | s.db.TrieDB().InsertBlob(common.BytesToHash(stateObject.CodeHash()), stateObject.code)
309 | stateObject.dirtyCode = false
310 | }
311 | if err := stateObject.CommitTrie(s.db); err != nil {//⑤
312 | return common.Hash{}, err
313 | }
314 | s.updateStateObject(stateObject)//⑥
315 | }
316 | delete(s.stateObjectsDirty, addr)
317 | }
318 | //...
319 | root, err = s.trie.Commit(func(leaf []byte, parent common.Hash) error {//⑦
320 | var account Account
321 | if err := rlp.DecodeBytes(leaf, &account); err != nil {
322 | return nil
323 | }
324 | if account.Root != emptyRoot {
325 | s.db.TrieDB().Reference(account.Root, parent)
326 | }
327 | code := common.BytesToHash(account.CodeHash)
328 | if code != emptyCode {
329 | s.db.TrieDB().Reference(code, parent)
330 | }
331 | return nil
332 | })
333 | return root, err
334 | }
335 | ```
336 |
337 |
338 |
339 | stateDB.Commit() will save the change to the db.
340 |
341 | 
342 |
343 | ### How StateDB revert change?
344 |
345 | When a transaction is packaged into a block, when one of the transactions fails to execute, the transaction will not be included in the block, and the state needs to be rolled back to the state before the execution of the transaction. The code below is the logic code for the mining module to process transactions.
346 |
347 | ```go
348 | snap := w.current.state.Snapshot()
349 | receipt, _, err := core.ApplyTransaction(w.config, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, *w.chain.GetVMConfig())
350 | if err != nil {
351 | w.current.state.RevertToSnapshot(snap)
352 | return nil, err
353 | }
354 | ```
--------------------------------------------------------------------------------
/ethereum/ethereum-block-and-network.md:
--------------------------------------------------------------------------------
1 | # Ethereum Block and Network
2 |
3 |
4 |
5 | In all blockchain projects, the data structure composed of blocks is one of the core. The reason why it is called "blockchain" is precisely because these projects organize all blocks in a chain structure, and Ethereum is no exception. Of course, in addition to the chain structure, some other functions have been added to Ethereum, such as the maintenance of uncle blocks, main chain and side chain, etc.
6 |
7 |
8 |
9 | The code about the blockchain structure in Ethereum is located in three directories:
10 |
11 | 1. core (only contains go files in the directory)
12 | 2. core/rawdb
13 | 3. light
14 |
15 |
16 |
17 | The go file in the core directory contains almost all important functions and is the core code of the Ethereum blockchain. Among them, the BlockChain structure and method implemented in blockchain.go is the core implementation; the HeaderChain implemented in headerchain.go realizes the management of block headers.
18 |
19 | The core/rawdb directory implements methods for **reading and writing all block structures from the database**. From these codes you can see how the blockchain is organized in the code.
20 |
21 | The code in the light directory implements the organization and maintenance of the blockchain **in the light synchronization mode** (described later).
22 |
23 |
24 |
25 | ### What is Block and Chain
26 |
27 | From wiki,
28 |
29 | > Blockchain is a series of transaction records (also known as blocks) that are connected and protected by cryptography. Each block contains the encrypted hash of the previous block, the corresponding time stamp and transaction data (usually represented by the hash value calculated by the Merkle tree algorithm) [7], this design makes the content of the block difficult to tamper characteristics. The distributed ledger connected by the blockchain allows two parties to effectively record the transaction, and the transaction can be permanently verified.
30 |
31 | Almost all blockchain projects are essentially about recording and confirming **transactions**. And this recording and confirmation is carried out through blocks. That is to say, after the miners check the legality of some **transactions**, they are packaged in the form of **blocks**, thus generating a new block data.
32 |
33 | In each block, there will be a field to record the hash of its parent block. It is the hash of this parent block that forms the block into a one-way list structure similar to the data structure, also known as a "chain".
34 |
35 | This is what blockchain is about.
36 | The method of using the hash of the parent block to form a chain can prevent the block from being tampered with, because if a block is modified, its hash will change, resulting in a discrepancy with the hash recorded in the child block, thus making this Such modifications are not recognized.
37 | The benefits of forming a chain also include easier handling of branching (i.e. forking). Just imagine that if blocks are organized in the form of an array, if there is a branch, it will definitely not be as convenient as a linked list.
38 |
39 |
40 |
41 | The chain maybe looks like this,
42 |
43 | 
44 |
45 |
46 |
47 |
48 |
49 | Most blocks form a chain, and each block points to its own parent block until the **Genesis block**. But it is also easy to notice that there is not only one chain from the beginning to the end, but there are many long or short branch chains like "burrs". These branch chains are called **side chains**, and the main chain is the **main chain**, and this situation of branch chains is called a **fork**.
50 |
51 | Each block will have a **height**, which is a count of the block's position on the chain. For example, the height of the genesis block is 0 because it is the first block. The height of the second block is 1, and so on. If we carefully observe the block height in the figure, we will find that the height of the last block on the main chain is not the largest. This shows that in Ethereum, the block height is not used to judge whether it is the main chain or the side chain. We will discuss this issue in more detail later.
52 |
53 | Regardless of whether it is the main chain or the side chain, some blocks on the side chain are "included" back, that is to say, some blocks will not only point to the parent block, but may also point to the blocks of their own uncles. This is a more distinctive feature in Ethereum, called uncle block.
54 |
55 | There are also some blocks that are not on the chain, these blocks are called **future blocks**. Ethereum sometimes receives some blocks with timestamps that are much larger than the parent block, so these blocks are temporarily stored as "future blocks". Try adding it to the chain when the time comes.
56 |
57 |
58 |
59 | ### Blocks
60 |
61 | In core/types/block.go
62 |
63 |
64 |
65 | ```go
66 | // Block represents an entire block in the Ethereum blockchain.
67 | type Block struct {
68 | header *Header
69 | uncles []*Header
70 | transactions Transactions
71 | withdrawals Withdrawals
72 |
73 | // caches
74 | hash atomic.Value
75 | size atomic.Value
76 |
77 | // These fields are used by package eth to track
78 | // inter-peer block relay.
79 | ReceivedAt time.Time
80 | ReceivedFrom interface{}
81 | }
82 |
83 | // Header represents a block header in the Ethereum blockchain.
84 | type Header struct {
85 | ParentHash common.Hash `json:"parentHash" gencodec:"required"`
86 | UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
87 | Coinbase common.Address `json:"miner"` //The address that accepts block rewards. Miners fill in their own addresses in this field when producing blocks.
88 | Root common.Hash `json:"stateRoot" gencodec:"required"` // Hash of state, after all transactions done
89 | TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` // hash of Block.transactions
90 | ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` // Receipt Hash
91 | Bloom Bloom `json:"logsBloom" gencodec:"required"` // bloom filter to find the log
92 | Difficulty *big.Int `json:"difficulty" gencodec:"required"`
93 | Number *big.Int `json:"number" gencodec:"required"`
94 | GasLimit uint64 `json:"gasLimit" gencodec:"required"` // Upper for gas
95 | GasUsed uint64 `json:"gasUsed" gencodec:"required"` // used gas
96 | Time uint64 `json:"timestamp" gencodec:"required"` // Timestamp
97 | Extra []byte `json:"extraData" gencodec:"required"` // extra Data, anything could be possible
98 | MixDigest common.Hash `json:"mixHash"` // hashimoto
99 | Nonce BlockNonce `json:"nonce"` //For PoW Miner
100 |
101 | // BaseFee was added by EIP-1559 and is ignored in legacy headers.
102 | BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
103 |
104 | // WithdrawalsHash was added by EIP-4895 and is ignored in legacy headers.
105 | WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
106 |
107 | /*
108 | TODO (MariusVanDerWijden) Add this field once needed
109 | // Random was added during the merge and contains the BeaconState randomness
110 | Random common.Hash `json:"random" rlp:"optional"`
111 | */
112 | }
113 | ```
114 |
115 | More important fields about Block,
116 |
117 | - Total Difficulty(Td)
118 |
119 | - ```go
120 | // TotalDifficultyAt calculates the total difficulty of the chain
121 | // at the given block height.
122 | func (c *Chain) TotalDifficultyAt(height int) *big.Int {
123 | sum := new(big.Int)
124 | if height >= c.Len() {
125 | return sum
126 | }
127 | for _, block := range c.blocks[:height+1] {
128 | sum.Add(sum, block.Difficulty())
129 | }
130 | return sum
131 | }
132 | ```
133 |
134 | - receipts
135 |
136 | - txlookupentries
137 |
138 | - It is used to query which block the transaction belongs to through the transaction hash.
139 |
140 | - state
141 |
142 | - all accounts info.
143 |
144 |
145 |
146 | ### Chain and sidechains
147 |
148 | The **chain** is the recognized chain, and subsequent newly generated blocks use the last block of the **chain** as the parent block.
149 |
150 | **Sidechains** are unacknowledged chains that may continue to grow, or stop there. If it continues to grow, its Td value may exceed the **chain** and become the **chain**. At this time, the original **chain** becomes a **sidechain** instead.
151 |
152 | Ideally, all blocks are added one by one on the **chain**. The reality is that the blockchain project is a distributed project, and the nodes did not trust each other before. Suppose nodes A and B generate a **block** with the same height, and they respectively tell other nodes about this news. Then some nodes add A's block to the **chain**, and some nodes add B's block to the **chain**. This situation creates a **fork**.
153 |
154 | If there is only one **chain** and nodes do not recognize other branches, then this **fork** will continue forever. This is obviously not acceptable.
155 |
156 | Therefore, in Ethereum, the **chain** and **sidechains** exist in the database at the same time. Every time a new **block** is added, it is re-judging whether the branch where the newly added block is located has become the **chain**. If it becomes the **chain**, it needs to be adjusted, and the branch where the newly added block is located becomes the **chain**, and the original **chain** is canceled at the same time.
157 |
158 |
159 |
160 | This is the code how Blockchain decide to reorg.
161 |
162 | ```go
163 | // writeBlockWithState writes block, metadata and corresponding state data to the
164 | // database.
165 | func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, state *state.StateDB) error {
166 | // Calculate the total difficulty of the block
167 | ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1)
168 | if ptd == nil {
169 | return consensus.ErrUnknownAncestor
170 | }
171 | // Make sure no inconsistent state is leaked during insertion
172 | externTd := new(big.Int).Add(block.Difficulty(), ptd)
173 |
174 | // Irrelevant of the canonical status, write the block itself to the database.
175 | //
176 | // Note all the components of block(td, hash->number map, header, body, receipts)
177 | // should be written atomically. BlockBatch is used for containing all components.
178 | blockBatch := bc.db.NewBatch()
179 | rawdb.WriteTd(blockBatch, block.Hash(), block.NumberU64(), externTd)
180 | rawdb.WriteBlock(blockBatch, block)
181 | rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receipts)
182 | rawdb.WritePreimages(blockBatch, state.Preimages())
183 | if err := blockBatch.Write(); err != nil {
184 | log.Crit("Failed to write block into disk", "err", err)
185 | }
186 | // Commit all cached state changes into underlying memory database.
187 | root, err := state.Commit(bc.chainConfig.IsEIP158(block.Number()))
188 | if err != nil {
189 | return err
190 | }
191 | // If we're running an archive node, always flush
192 | if bc.cacheConfig.TrieDirtyDisabled {
193 | return bc.triedb.Commit(root, false)
194 | }
195 | // Full but not archive node, do proper garbage collection
196 | bc.triedb.Reference(root, common.Hash{}) // metadata reference to keep trie alive
197 | bc.triegc.Push(root, -int64(block.NumberU64()))
198 |
199 | current := block.NumberU64()
200 | // Flush limits are not considered for the first TriesInMemory blocks.
201 | if current <= TriesInMemory {
202 | return nil
203 | }
204 | // If we exceeded our memory allowance, flush matured singleton nodes to disk
205 | var (
206 | nodes, imgs = bc.triedb.Size()
207 | limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024
208 | )
209 | if nodes > limit || imgs > 4*1024*1024 {
210 | bc.triedb.Cap(limit - ethdb.IdealBatchSize)
211 | }
212 | // Find the next state trie we need to commit
213 | chosen := current - TriesInMemory
214 | flushInterval := time.Duration(atomic.LoadInt64(&bc.flushInterval))
215 | // If we exceeded time allowance, flush an entire trie to disk
216 | if bc.gcproc > flushInterval {
217 | // If the header is missing (canonical chain behind), we're reorging a low
218 | // diff sidechain. Suspend committing until this operation is completed.
219 | header := bc.GetHeaderByNumber(chosen)
220 | if header == nil {
221 | log.Warn("Reorg in progress, trie commit postponed", "number", chosen)
222 | } else {
223 | // If we're exceeding limits but haven't reached a large enough memory gap,
224 | // warn the user that the system is becoming unstable.
225 | if chosen < bc.lastWrite+TriesInMemory && bc.gcproc >= 2*flushInterval {
226 | log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", flushInterval, "optimum", float64(chosen-bc.lastWrite)/TriesInMemory)
227 | }
228 | // Flush an entire trie and restart the counters
229 | bc.triedb.Commit(header.Root, true)
230 | bc.lastWrite = chosen
231 | bc.gcproc = 0
232 | }
233 | }
234 | // Garbage collect anything below our required write retention
235 | for !bc.triegc.Empty() {
236 | root, number := bc.triegc.Pop()
237 | if uint64(-number) > chosen {
238 | bc.triegc.Push(root, number)
239 | break
240 | }
241 | bc.triedb.Dereference(root)
242 | }
243 | return nil
244 | }
245 | ```
246 |
247 |
248 |
249 | This is the Blockchain how to reorg.
250 |
251 | ```go
252 | // reorg takes two blocks, an old chain and a new chain and will reconstruct the
253 | // blocks and inserts them to be part of the new canonical chain and accumulates
254 | // potential missing transactions and post an event about them.
255 | // Note the new head block won't be processed here, callers need to handle it
256 | // externally.
257 | func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
258 | var (
259 | newChain types.Blocks
260 | oldChain types.Blocks
261 | commonBlock *types.Block
262 |
263 | deletedTxs []common.Hash
264 | addedTxs []common.Hash
265 | )
266 | // Reduce the longer chain to the same number as the shorter one
267 | // Find the common ancestor commonBlock of the two branches of oldBlock and newBlock, Record all blocks on the path to the common ancestor in newChain and oldChain respectively. At the same time, put all transactions on the branch of oldBlock into deletedTxs.
268 | if oldBlock.NumberU64() > newBlock.NumberU64() {
269 | ...
270 | }
271 | }
272 | ```
273 |
274 |
275 |
276 | The method of writing a block to the main chain is actually very simple, that is, to create a record from the block height to the block hash in the database. When we only use the block height to get a block, what we get is the block on the main chain; at the same time, the main chain will have a mark that records the hash of the latest block on the main chain.
277 |
278 |
279 |
280 | ### pruned block
281 |
282 | In October 2017, the data of Ethereum had reached more than 300G, and it would soon exceed 1T. Such a large amount of data is unacceptable for an ordinary user.
283 |
284 | The Ethereum team solved this problem by pruning block data. To be precise, what is pruned is actually state data, because the final reason for the rapid growth of Ethereum data is not the increase in the number of blocks, but the growth of state data. So why does the amount of state data grow so fast? This starts with how the state is implemented.
285 |
286 |
287 |
288 | Is it necessary for an Ethereum node to store all historical data of the state? In most cases it is not needed. For those data that are not needed, we can not store them. In case we need to use it one day, we can spend some time to recalculate the data because the complete block information is saved.
289 |
290 | The method provided by Ethereum is to prune the nodes of the trie tree. In the implementation of trie, "reference counting" will be performed on the nodes existing in memory, that is, each node has a number that records the number of times it is referenced. When the number of references becomes 0, the node memory will be released. will not be written to the database.
291 |
292 |
293 |
294 | ### 3 Synchronization Modes
295 |
296 | full、fast、light.
297 |
298 | ##### full mode
299 |
300 | As the name suggests, "full mode" synchronizes all block data. In full mode, the synchronization module calls BlockChain.InsertChain to insert block data obtained from other nodes into the database. In BlockChain.InsertChain, the state and receipts data of each block will be calculated and verified one by one. If everything is normal, the synchronized block data and the state and receipts data calculated by itself will be written into the database together.
301 |
302 | Note that there are two processing methods in full mode, one of which saves all historical data, and this node is called "archive node". The other prunes the state. To become an "archive node", set the NoPruning field in the configuration file to true.
303 |
304 | ##### fast mode
305 |
306 | The so-called "quick mode" is relative to the "full mode". In full mode, the state and receipts are calculated on the current machine based on the transactions in the block data. In fast mode, state and receipts are no longer calculated locally, but are directly synchronized from other nodes just like block data. Therefore, in the fast mode, the synchronous mode calls BlockChain.InsertReceiptChain to write the synchronized blocks and receipts directly into the blockchain database; and the state is also directly written into the library through stateDb.
307 |
308 | There is a currentFastBlock field in BlockChain, which represents the latest block on the main chain in fast mode.
309 |
310 | It can be seen that the fast mode replaces the local calculation of the state and receipts in the full mode by using the network direct synchronization method, and replaces the local computing resources with the network bandwidth.
311 |
312 | ##### light mode
313 |
314 | Light mode, also called light mode, is a mode that only synchronizes block headers. In the light mode, the blockchain organization does not use the blockchain module, but the light module. This module is located in the "light" directory under the Ethereum project. The biggest difference from the blockchain module is that the light module only calls the related methods of HeaderChain to process the block header, but not other data. Only when other data other than the header of a certain block is needed, the required data is obtained.
315 |
316 | When calling loadLastState, if the state of currentBlock does not exist, then call repair to obtain and search up the currentBlock until a state exists.
317 |
318 |
319 |
320 |
321 |
322 | ### Questions
323 |
324 |
325 |
326 | - What is the average block interval time of Ethereum?
327 | - The average block interval time of Ethereum is around 13-15 seconds
328 | - What is the average block size of Ethereum?
329 | - The average block size of Ethereum varies depending on the number of transactions being processed, but it typically ranges between 20-30 kilobytes.
330 | - What are nodes in Ethereum? How can one connect to Ethereum nodes?
331 | - Nodes in Ethereum refer to any computer or device that is connected to the Ethereum network and participates in validating transactions and maintaining the blockchain. One can connect to Ethereum nodes using a client program such as Geth or Parity, which allows communication with the network through the use of JSON-RPC APIs.
332 | - What are the methods for interacting with the Ethereum network?
333 | - There are several methods for interacting with the Ethereum network, including:
334 | - Using a client program such as Geth or Parity
335 | - Using a web3.js library to communicate with the network through a web browser
336 | - Utilizing a third-party service or API provider
337 | - Deploying and interacting with smart contracts on the Ethereum Virtual Machine (EVM)
338 | - Name some Types of Ethereum Networks?
339 | - Some types of Ethereum networks include the mainnet, testnets such as Ropsten and Rinkeby, and private networks used for development and testing purposes.
340 | - What is an Ethereum Client?
341 | - An Ethereum client is a software program that is used to connect to the Ethereum network and participate in the validation of transactions and maintenance of the blockchain. Examples of Ethereum clients include Geth, Parity, and Besu.
342 | - How does a blockchain recognize a Block?
343 | - A blockchain recognizes a block through a combination of its hash value, which is calculated based on the transactions contained within the block, and the hash value of the previous block in the chain. When a new block is added to the blockchain, it must be validated by a network of nodes to ensure that its hash value matches the previous block and that its transactions are valid.
344 | - In a Blockchain database, what various kinds of records can you find?
345 | - In a blockchain database, you can find various kinds of records, including transactions, blocks, addresses, and smart contracts. Transactions record the transfer of cryptocurrency or other assets between parties, blocks group transactions together and form the basis of the blockchain, addresses are unique identifiers used to send and receive assets, and smart contracts are self-executing code that can be deployed and executed on the blockchain.
346 | - Is it possible to make changes to the data after it has been written in a block?
347 | - Once data has been written to a block on the blockchain, it is extremely difficult, if not impossible, to change it. This is because the blockchain uses a cryptographic hash function to link each block to the previous one, creating an immutable chain of blocks. Any attempt to modify the data in a block would change its hash value, which would in turn invalidate all the subsequent blocks in the chain. Therefore, the blockchain is considered to be a secure and tamper-resistant way to store data.
348 | - Why use Ethereum private chains when the Ethereum main chain is already powerful?
349 | - While the Ethereum main chain is powerful and widely used, there are situations where a private Ethereum blockchain may be more appropriate. Private chains offer greater control over the network, allowing organizations to customize network parameters and restrict access to specific participants. This can be useful for companies that require a high degree of privacy, security, and control over their data and applications. Private chains can also offer faster transaction times and lower transaction fees compared to the public Ethereum network.
350 | - How can I view detailed information about a transaction or block?
351 | - To view detailed information about a transaction or block on the Ethereum main chain, you can use a blockchain explorer such as Etherscan. Simply enter the transaction hash or block number into the search bar and you will be able to see detailed information about the transaction or block, including the sender and recipient addresses, transaction fee, gas used, and more.
352 | - How can I view detailed information about a transaction or block on a private Ethereum chain?
353 | - To view detailed information about a transaction or block on a private Ethereum chain, you will need to access the blockchain's node or use a blockchain explorer specifically designed for that private chain. Depending on the specific implementation of the private chain, you may need to obtain special permissions or access credentials to view this information.
--------------------------------------------------------------------------------
/ethereum/erc721-token.md:
--------------------------------------------------------------------------------
1 | # ERC-721
2 |
3 | ```solidity
4 | pragma solidity ^0.8.0;
5 |
6 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
7 | import "@openzeppelin/contracts/utils/Counters.sol";
8 |
9 | contract MyNFT is ERC721 {
10 | using Counters for Counters.Counter;
11 | Counters.Counter private _tokenIds;
12 |
13 | constructor() ERC721("MyNFT", "MNFT") {}
14 |
15 | function createToken(address owner, string memory tokenURI) public returns (uint256) {
16 | _tokenIds.increment();
17 |
18 | uint256 newTokenId = _tokenIds.current();
19 | _mint(owner, newTokenId);
20 | _setTokenURI(newTokenId, tokenURI);
21 |
22 | return newTokenId;
23 | }
24 | }
25 |
26 | MyNFT myNFT = new MyNFT();
27 |
28 | for (uint i=0; i<20; i++) {
29 | string memory tokenURI = string(abi.encodePacked("https://example.com/nft/", i));
30 | myNFT.createToken(msg.sender, tokenURI);
31 | }
32 | ```
33 |
34 |
35 |
36 | ### BoredApeYachtClub
37 |
38 | Let us see the smart contract of BoredApeYachtClub (BAYC).
39 |
40 | https://etherscan.io/token/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d#code
41 |
42 | ```solidity
43 | ...
44 |
45 | /**
46 | * @title ERC721 Non-Fungible Token Standard basic implementation
47 | * @dev see https://eips.ethereum.org/EIPS/eip-721
48 | */
49 | contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {
50 | using SafeMath for uint256;
51 | using Address for address;
52 | using EnumerableSet for EnumerableSet.UintSet;
53 | using EnumerableMap for EnumerableMap.UintToAddressMap;
54 | using Strings for uint256;
55 |
56 | // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
57 | // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
58 | bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
59 |
60 | // Mapping from holder address to their (enumerable) set of owned tokens
61 | mapping (address => EnumerableSet.UintSet) private _holderTokens;
62 |
63 | // Enumerable mapping from token ids to their owners
64 | EnumerableMap.UintToAddressMap private _tokenOwners;
65 |
66 | // Mapping from token ID to approved address
67 | mapping (uint256 => address) private _tokenApprovals;
68 |
69 | // Mapping from owner to operator approvals
70 | mapping (address => mapping (address => bool)) private _operatorApprovals;
71 |
72 | // Token name
73 | string private _name;
74 |
75 | // Token symbol
76 | string private _symbol;
77 |
78 | // Optional mapping for token URIs
79 | mapping (uint256 => string) private _tokenURIs;
80 |
81 | // Base URI
82 | string private _baseURI;
83 |
84 | /*
85 | * bytes4(keccak256('balanceOf(address)')) == 0x70a08231
86 | * bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
87 | * bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
88 | * bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
89 | * bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
90 | * bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
91 | * bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
92 | * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
93 | * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
94 | *
95 | * => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
96 | * 0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
97 | */
98 | bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
99 |
100 | /*
101 | * bytes4(keccak256('name()')) == 0x06fdde03
102 | * bytes4(keccak256('symbol()')) == 0x95d89b41
103 | * bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
104 | *
105 | * => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
106 | */
107 | bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
108 |
109 | /*
110 | * bytes4(keccak256('totalSupply()')) == 0x18160ddd
111 | * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
112 | * bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
113 | *
114 | * => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
115 | */
116 | bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;
117 |
118 | /**
119 | * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
120 | */
121 | constructor (string memory name_, string memory symbol_) public {
122 | _name = name_;
123 | _symbol = symbol_;
124 |
125 | // register the supported interfaces to conform to ERC721 via ERC165
126 | _registerInterface(_INTERFACE_ID_ERC721);
127 | _registerInterface(_INTERFACE_ID_ERC721_METADATA);
128 | _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
129 | }
130 |
131 | /**
132 | * @dev See {IERC721-balanceOf}.
133 | */
134 | function balanceOf(address owner) public view virtual override returns (uint256) {
135 | require(owner != address(0), "ERC721: balance query for the zero address");
136 | return _holderTokens[owner].length();
137 | }
138 |
139 | /**
140 | * @dev See {IERC721-ownerOf}.
141 | */
142 | function ownerOf(uint256 tokenId) public view virtual override returns (address) {
143 | return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
144 | }
145 |
146 | /**
147 | * @dev See {IERC721Metadata-name}.
148 | */
149 | function name() public view virtual override returns (string memory) {
150 | return _name;
151 | }
152 |
153 | /**
154 | * @dev See {IERC721Metadata-symbol}.
155 | */
156 | function symbol() public view virtual override returns (string memory) {
157 | return _symbol;
158 | }
159 |
160 | /**
161 | * @dev See {IERC721Metadata-tokenURI}.
162 | */
163 | function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
164 | require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
165 |
166 | string memory _tokenURI = _tokenURIs[tokenId];
167 | string memory base = baseURI();
168 |
169 | // If there is no base URI, return the token URI.
170 | if (bytes(base).length == 0) {
171 | return _tokenURI;
172 | }
173 | // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
174 | if (bytes(_tokenURI).length > 0) {
175 | return string(abi.encodePacked(base, _tokenURI));
176 | }
177 | // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
178 | return string(abi.encodePacked(base, tokenId.toString()));
179 | }
180 |
181 | /**
182 | * @dev Returns the base URI set via {_setBaseURI}. This will be
183 | * automatically added as a prefix in {tokenURI} to each token's URI, or
184 | * to the token ID if no specific URI is set for that token ID.
185 | */
186 | function baseURI() public view virtual returns (string memory) {
187 | return _baseURI;
188 | }
189 |
190 | /**
191 | * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
192 | */
193 | function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
194 | return _holderTokens[owner].at(index);
195 | }
196 |
197 | /**
198 | * @dev See {IERC721Enumerable-totalSupply}.
199 | */
200 | function totalSupply() public view virtual override returns (uint256) {
201 | // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds
202 | return _tokenOwners.length();
203 | }
204 |
205 | /**
206 | * @dev See {IERC721Enumerable-tokenByIndex}.
207 | */
208 | function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
209 | (uint256 tokenId, ) = _tokenOwners.at(index);
210 | return tokenId;
211 | }
212 |
213 | /**
214 | * @dev See {IERC721-approve}.
215 | */
216 | function approve(address to, uint256 tokenId) public virtual override {
217 | address owner = ERC721.ownerOf(tokenId);
218 | require(to != owner, "ERC721: approval to current owner");
219 |
220 | require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),
221 | "ERC721: approve caller is not owner nor approved for all"
222 | );
223 |
224 | _approve(to, tokenId);
225 | }
226 |
227 | /**
228 | * @dev See {IERC721-getApproved}.
229 | */
230 | function getApproved(uint256 tokenId) public view virtual override returns (address) {
231 | require(_exists(tokenId), "ERC721: approved query for nonexistent token");
232 |
233 | return _tokenApprovals[tokenId];
234 | }
235 |
236 | /**
237 | * @dev See {IERC721-setApprovalForAll}.
238 | */
239 | function setApprovalForAll(address operator, bool approved) public virtual override {
240 | require(operator != _msgSender(), "ERC721: approve to caller");
241 |
242 | _operatorApprovals[_msgSender()][operator] = approved;
243 | emit ApprovalForAll(_msgSender(), operator, approved);
244 | }
245 |
246 | /**
247 | * @dev See {IERC721-isApprovedForAll}.
248 | */
249 | function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
250 | return _operatorApprovals[owner][operator];
251 | }
252 |
253 | /**
254 | * @dev See {IERC721-transferFrom}.
255 | */
256 | function transferFrom(address from, address to, uint256 tokenId) public virtual override {
257 | //solhint-disable-next-line max-line-length
258 | require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
259 |
260 | _transfer(from, to, tokenId);
261 | }
262 |
263 | /**
264 | * @dev See {IERC721-safeTransferFrom}.
265 | */
266 | function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
267 | safeTransferFrom(from, to, tokenId, "");
268 | }
269 |
270 | /**
271 | * @dev See {IERC721-safeTransferFrom}.
272 | */
273 | function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {
274 | require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
275 | _safeTransfer(from, to, tokenId, _data);
276 | }
277 |
278 | /**
279 | * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
280 | * are aware of the ERC721 protocol to prevent tokens from being forever locked.
281 | *
282 | * `_data` is additional data, it has no specified format and it is sent in call to `to`.
283 | *
284 | * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
285 | * implement alternative mechanisms to perform token transfer, such as signature-based.
286 | *
287 | * Requirements:
288 | *
289 | * - `from` cannot be the zero address.
290 | * - `to` cannot be the zero address.
291 | * - `tokenId` token must exist and be owned by `from`.
292 | * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
293 | *
294 | * Emits a {Transfer} event.
295 | */
296 | function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {
297 | _transfer(from, to, tokenId);
298 | require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
299 | }
300 |
301 | /**
302 | * @dev Returns whether `tokenId` exists.
303 | *
304 | * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
305 | *
306 | * Tokens start existing when they are minted (`_mint`),
307 | * and stop existing when they are burned (`_burn`).
308 | */
309 | function _exists(uint256 tokenId) internal view virtual returns (bool) {
310 | return _tokenOwners.contains(tokenId);
311 | }
312 |
313 | /**
314 | * @dev Returns whether `spender` is allowed to manage `tokenId`.
315 | *
316 | * Requirements:
317 | *
318 | * - `tokenId` must exist.
319 | */
320 | function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
321 | require(_exists(tokenId), "ERC721: operator query for nonexistent token");
322 | address owner = ERC721.ownerOf(tokenId);
323 | return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));
324 | }
325 |
326 | /**
327 | * @dev Safely mints `tokenId` and transfers it to `to`.
328 | *
329 | * Requirements:
330 | d*
331 | * - `tokenId` must not exist.
332 | * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
333 | *
334 | * Emits a {Transfer} event.
335 | */
336 | function _safeMint(address to, uint256 tokenId) internal virtual {
337 | _safeMint(to, tokenId, "");
338 | }
339 |
340 | /**
341 | * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
342 | * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
343 | */
344 | function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {
345 | _mint(to, tokenId);
346 | require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
347 | }
348 |
349 | /**
350 | * @dev Mints `tokenId` and transfers it to `to`.
351 | *
352 | * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
353 | *
354 | * Requirements:
355 | *
356 | * - `tokenId` must not exist.
357 | * - `to` cannot be the zero address.
358 | *
359 | * Emits a {Transfer} event.
360 | */
361 | function _mint(address to, uint256 tokenId) internal virtual {
362 | require(to != address(0), "ERC721: mint to the zero address");
363 | require(!_exists(tokenId), "ERC721: token already minted");
364 |
365 | _beforeTokenTransfer(address(0), to, tokenId);
366 |
367 | _holderTokens[to].add(tokenId);
368 |
369 | _tokenOwners.set(tokenId, to);
370 |
371 | emit Transfer(address(0), to, tokenId);
372 | }
373 |
374 | /**
375 | * @dev Destroys `tokenId`.
376 | * The approval is cleared when the token is burned.
377 | *
378 | * Requirements:
379 | *
380 | * - `tokenId` must exist.
381 | *
382 | * Emits a {Transfer} event.
383 | */
384 | function _burn(uint256 tokenId) internal virtual {
385 | address owner = ERC721.ownerOf(tokenId); // internal owner
386 |
387 | _beforeTokenTransfer(owner, address(0), tokenId);
388 |
389 | // Clear approvals
390 | _approve(address(0), tokenId);
391 |
392 | // Clear metadata (if any)
393 | if (bytes(_tokenURIs[tokenId]).length != 0) {
394 | delete _tokenURIs[tokenId];
395 | }
396 |
397 | _holderTokens[owner].remove(tokenId);
398 |
399 | _tokenOwners.remove(tokenId);
400 |
401 | emit Transfer(owner, address(0), tokenId);
402 | }
403 |
404 | /**
405 | * @dev Transfers `tokenId` from `from` to `to`.
406 | * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
407 | *
408 | * Requirements:
409 | *
410 | * - `to` cannot be the zero address.
411 | * - `tokenId` token must be owned by `from`.
412 | *
413 | * Emits a {Transfer} event.
414 | */
415 | function _transfer(address from, address to, uint256 tokenId) internal virtual {
416 | require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); // internal owner
417 | require(to != address(0), "ERC721: transfer to the zero address");
418 |
419 | _beforeTokenTransfer(from, to, tokenId);
420 |
421 | // Clear approvals from the previous owner
422 | _approve(address(0), tokenId);
423 |
424 | _holderTokens[from].remove(tokenId);
425 | _holderTokens[to].add(tokenId);
426 |
427 | _tokenOwners.set(tokenId, to);
428 |
429 | emit Transfer(from, to, tokenId);
430 | }
431 |
432 | /**
433 | * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
434 | *
435 | * Requirements:
436 | *
437 | * - `tokenId` must exist.
438 | */
439 | function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
440 | require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
441 | _tokenURIs[tokenId] = _tokenURI;
442 | }
443 |
444 | /**
445 | * @dev Internal function to set the base URI for all token IDs. It is
446 | * automatically added as a prefix to the value returned in {tokenURI},
447 | * or to the token ID if {tokenURI} is empty.
448 | */
449 | function _setBaseURI(string memory baseURI_) internal virtual {
450 | _baseURI = baseURI_;
451 | }
452 |
453 | /**
454 | * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
455 | * The call is not executed if the target address is not a contract.
456 | *
457 | * @param from address representing the previous owner of the given token ID
458 | * @param to target address that will receive the tokens
459 | * @param tokenId uint256 ID of the token to be transferred
460 | * @param _data bytes optional data to send along with the call
461 | * @return bool whether the call correctly returned the expected magic value
462 | */
463 | function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
464 | private returns (bool)
465 | {
466 | if (!to.isContract()) {
467 | return true;
468 | }
469 | bytes memory returndata = to.functionCall(abi.encodeWithSelector(
470 | IERC721Receiver(to).onERC721Received.selector,
471 | _msgSender(),
472 | from,
473 | tokenId,
474 | _data
475 | ), "ERC721: transfer to non ERC721Receiver implementer");
476 | bytes4 retval = abi.decode(returndata, (bytes4));
477 | return (retval == _ERC721_RECEIVED);
478 | }
479 |
480 | /**
481 | * @dev Approve `to` to operate on `tokenId`
482 | *
483 | * Emits an {Approval} event.
484 | */
485 | function _approve(address to, uint256 tokenId) internal virtual {
486 | _tokenApprovals[tokenId] = to;
487 | emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner
488 | }
489 |
490 | /**
491 | * @dev Hook that is called before any token transfer. This includes minting
492 | * and burning.
493 | *
494 | * Calling conditions:
495 | *
496 | * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
497 | * transferred to `to`.
498 | * - When `from` is zero, `tokenId` will be minted for `to`.
499 | * - When `to` is zero, ``from``'s `tokenId` will be burned.
500 | * - `from` cannot be the zero address.
501 | * - `to` cannot be the zero address.
502 | *
503 | * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
504 | */
505 | function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }
506 | }
507 |
508 | // File: @openzeppelin/contracts/access/Ownable.sol
509 |
510 |
511 |
512 | ...
513 |
514 | pragma solidity ^0.7.0;
515 |
516 |
517 |
518 | /**
519 | * @title BoredApeYachtClub contract
520 | * @dev Extends ERC721 Non-Fungible Token Standard basic implementation
521 | */
522 | contract BoredApeYachtClub is ERC721, Ownable {
523 | using SafeMath for uint256;
524 |
525 | string public BAYC_PROVENANCE = "";
526 |
527 | uint256 public startingIndexBlock;
528 |
529 | uint256 public startingIndex;
530 |
531 | // price to build an ape
532 | uint256 public constant apePrice = 80000000000000000; //0.08 ETH
533 |
534 | uint public constant maxApePurchase = 20;
535 |
536 | uint256 public MAX_APES; // This is very important. This number ensures that there is an upper limit to the number of apes. And this number cannot be updated.
537 |
538 | bool public saleIsActive = false;
539 |
540 | uint256 public REVEAL_TIMESTAMP;
541 |
542 | constructor(string memory name, string memory symbol, uint256 maxNftSupply, uint256 saleStart) ERC721(name, symbol) {
543 | MAX_APES = maxNftSupply;
544 | REVEAL_TIMESTAMP = saleStart + (86400 * 9);
545 | }
546 |
547 | // Send balance of the contract account to owner acc
548 | function withdraw() public onlyOwner {
549 | uint balance = address(this).balance;
550 | msg.sender.transfer(balance);
551 | }
552 |
553 | /**
554 | * Set some Bored Apes aside
555 | * build 30 apes
556 | */
557 | function reserveApes() public onlyOwner {
558 | uint supply = totalSupply();
559 | uint i;
560 | for (i = 0; i < 30; i++) {
561 | _safeMint(msg.sender, supply + i);
562 | }
563 | }
564 |
565 | /**
566 | * DM Gargamel in Discord that you're standing right behind him.
567 | */
568 | function setRevealTimestamp(uint256 revealTimeStamp) public onlyOwner {
569 | REVEAL_TIMESTAMP = revealTimeStamp;
570 | }
571 |
572 | /*
573 | * Set provenance once it's calculated
574 | */
575 | function setProvenanceHash(string memory provenanceHash) public onlyOwner {
576 | BAYC_PROVENANCE = provenanceHash;
577 | }
578 |
579 | function setBaseURI(string memory baseURI) public onlyOwner {
580 | _setBaseURI(baseURI);
581 | }
582 |
583 | /*
584 | * Pause sale if active, make active if paused
585 | */
586 | function flipSaleState() public onlyOwner {
587 | saleIsActive = !saleIsActive;
588 | }
589 |
590 | /**
591 | * Mints Bored Apes
592 | */
593 | function mintApe(uint numberOfTokens) public payable {
594 | require(saleIsActive, "Sale must be active to mint Ape");
595 | require(numberOfTokens <= maxApePurchase, "Can only mint 20 tokens at a time");
596 | require(totalSupply().add(numberOfTokens) <= MAX_APES, "Purchase would exceed max supply of Apes");
597 | require(apePrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");
598 |
599 | for(uint i = 0; i < numberOfTokens; i++) {
600 | uint mintIndex = totalSupply();
601 | if (totalSupply() < MAX_APES) {
602 | _safeMint(msg.sender, mintIndex);
603 | }
604 | }
605 |
606 | // If we haven't set the starting index and this is either 1) the last saleable token or 2) the first token to be sold after
607 | // the end of pre-sale, set the starting index block
608 | if (startingIndexBlock == 0 && (totalSupply() == MAX_APES || block.timestamp >= REVEAL_TIMESTAMP)) {
609 | startingIndexBlock = block.number;
610 | }
611 | }
612 |
613 | /**
614 | * Set the starting index for the collection
615 | */
616 | function setStartingIndex() public {
617 | require(startingIndex == 0, "Starting index is already set");
618 | require(startingIndexBlock != 0, "Starting index block must be set");
619 |
620 | startingIndex = uint(blockhash(startingIndexBlock)) % MAX_APES;
621 | // Just a sanity case in the worst case if this function is called late (EVM only stores last 256 block hashes)
622 | if (block.number.sub(startingIndexBlock) > 255) {
623 | startingIndex = uint(blockhash(block.number - 1)) % MAX_APES;
624 | }
625 | // Prevent default sequence
626 | if (startingIndex == 0) {
627 | startingIndex = startingIndex.add(1);
628 | }
629 | }
630 |
631 | /**
632 | * Set the starting index block for the collection, essentially unblocking
633 | * setting starting index
634 | */
635 | function emergencySetStartingIndexBlock() public onlyOwner {
636 | require(startingIndex == 0, "Starting index is already set");
637 |
638 | startingIndexBlock = block.number;
639 | }
640 | }
641 | ```
642 |
643 |
644 |
645 |
646 |
647 | We can see that the essence of NFT is to associate a blockchain account with a string.
648 |
649 | The author of BoredApeYachtClub first drew 30 pictures of monkeys, and then uploaded the pictures to a website to obtain a URL.
650 |
651 | Any purchase of NFT from them means that they will add a record that associates the URL corresponding to the picture with the buyer's address.
652 |
653 | Buyers then claim that they own the URL.
654 |
655 | Can other people get pictures through this URL? is allowed. Anyone can download this image and modify it.
656 |
657 | This is because the ownership of NFT is recorded on the blockchain, so the generation and transfer of NFT is absolutely clear, but the ownership of NFT is completely separated from the use value of NFT.
658 |
659 | Currently one of the cheapest monkeys is 70ETH, about $100,000.
--------------------------------------------------------------------------------
/ethereum/solidity.md:
--------------------------------------------------------------------------------
1 | # Solidity
2 |
3 |
4 |
5 | ```solidity
6 | pragma solidity ^0.4.21;
7 |
8 | contract Coin {
9 | address public minter;
10 | mapping (address => uint) public balances;
11 |
12 | event Sent(address from, address to, uint amount);
13 |
14 | // when we create a contract, we call this.
15 | function Coin() public {
16 | minter = msg.sender;
17 | }
18 |
19 | // receiver and amount are from Calldata
20 | function mint(address receiver, uint amount) public {
21 | if (msg.sender != minter) return;
22 | balances[receiver] += amount;
23 | }
24 |
25 | function send(address receiver, uint amount) public {
26 | if (balances[msg.sender] < amount) return;
27 | balances[msg.sender] -= amount;
28 | balances[receiver] += amount;
29 | emit Sent(msg.sender, receiver, amount);
30 | }
31 | }
32 | ```
33 |
34 | 1. When each smart contract is created, it will rely on a smart contract account.
35 |
36 | 2. Each smart contract account has a storage, which is a KV database. Minter and balances in the instance will enter it, and there is no clear maximum capacity limit for storage.
37 |
38 | 3. Every call to a smart contract function is equivalent to a transaction, and the transaction needs to be recorded in the block. The Ethereum blockchain can only produce one block at a time. This ensures orderliness.
39 |
40 | 4. Essentially any node can execute the function, which is concurrent. But only one execution result is recognized.
41 |
42 | 5. As long as it is a variable stored in storage, it can be obtained directly without executing the contract function.
43 |
44 | 6. Read-only Calldata changes the state of storage, which is the nature of most functions.
45 |
46 | 7. The payable function modifier enables Solidity contracts to accept payment in ether
47 |
48 | 8. When an error is reported in the middle of the execution of the function of the smart contract, the function state will automatically roll back to the state before the function execution to ensure that the state of the contract will not be modified to an invalid or inconsistent state.
49 |
50 |
51 |
52 | ### Global Variables
53 |
54 | There are many predefined global variables in Solidity, here are some common ones:
55 |
56 | 1. msg.sender - contains the address of the caller of the current function, used to verify the identity of the caller.
57 | 2. msg.value - Contains the amount of ether sent by the caller of the current function for receiving ether in the smart contract.
58 | 3. now - the timestamp of the current block (in seconds), which can be used to get the current time in the smart contract.
59 | 4. block.timestamp - the timestamp (in seconds) of the current block, same as the now variable.
60 | 5. block.number - the block number of the current block.
61 | 6. address(this) - the address of the current smart contract, used to refer to itself in the smart contract.
62 | 7. tx.origin - Contains the sender address of the transaction, not the address of the calling contract. Normally, tx.origin should not be used to authenticate the caller.
63 | 8. gasleft() - contains how much gas is left in the current transaction, which can be used to determine the gas usage of the current transaction in the smart contract.
64 |
65 | These global variables provide a convenient way to obtain various information in smart contracts, and can be used to write various types of smart contracts. However, they need to be used with care to avoid security holes and misbehavior.
66 |
67 |
68 |
69 |
70 |
71 | ### USDT
72 |
73 |
74 |
75 | ```solidity
76 | /**
77 | *Submitted for verification at Etherscan.io on 2017-11-28
78 | */
79 |
80 | pragma solidity ^0.4.17;
81 | ```
82 |
83 | The pragma instructs to use a specific version of Solidity. ^0.4.17 means to use 0.4.17 and all latest versions that are upwardly compatible with that version, such as 0.4.18, 0.4.19, etc. If you declare a version with the "^" symbol, the compiler will automatically select the latest version that is upwardly compatible with the current Solidity compiler version for compilation.
84 |
85 | ```solidity
86 | /**
87 | * @title SafeMath
88 | * @dev Math operations with safety checks that throw on error
89 | */
90 | library SafeMath {
91 | function mul(uint256 a, uint256 b) internal pure returns (uint256) {
92 | if (a == 0) {
93 | return 0;
94 | }
95 | uint256 c = a * b;
96 | assert(c / a == b);
97 | return c;
98 | }
99 |
100 | function div(uint256 a, uint256 b) internal pure returns (uint256) {
101 | // assert(b > 0); // Solidity automatically throws when dividing by 0
102 | uint256 c = a / b;
103 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold
104 | return c;
105 | }
106 |
107 | function sub(uint256 a, uint256 b) internal pure returns (uint256) {
108 | assert(b <= a);
109 | return a - b;
110 | }
111 |
112 | function add(uint256 a, uint256 b) internal pure returns (uint256) {
113 | uint256 c = a + b;
114 | assert(c >= a);
115 | return c;
116 | }
117 | }
118 | ```
119 |
120 |
121 |
122 | - `library`: Indicates that this is a Solidity library (library), used to implement reusable code modules, be careful using other people's libraries.
123 | - `internal`: Indicates that this function can only be called inside the current contract or its inherited contracts, and cannot be called from outside the contract.
124 | - `pure`: Indicates that this function will not modify the state of the contract, and will not access the storage variables of the contract, nor will it interact with other contracts.
125 | - `returns`: indicates that this function will return one or more values.
126 | - `assert`: Indicates that if the function execution fails, an exception will be thrown (that is, the assertion failed) to terminate the program execution.
127 |
128 |
129 |
130 |
131 |
132 | ```solidity
133 | /**
134 | * @title Ownable
135 | * @dev The Ownable contract has an owner address, and provides basic authorization control
136 | * functions, this simplifies the implementation of "user permissions".
137 | */
138 | contract Ownable {
139 | address public owner;
140 |
141 | /**
142 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender
143 | * account.
144 | */
145 | function Ownable() public {
146 | owner = msg.sender;
147 | }
148 |
149 | /**
150 | * @dev Throws if called by any account other than the owner.
151 | */
152 | modifier onlyOwner() {
153 | require(msg.sender == owner);
154 | _;
155 | }
156 |
157 | /**
158 | * @dev Allows the current owner to transfer control of the contract to a newOwner.
159 | * @param newOwner The address to transfer ownership to.
160 | */
161 | function transferOwnership(address newOwner) public onlyOwner {
162 | if (newOwner != address(0)) {
163 | owner = newOwner;
164 | }
165 | }
166 |
167 | }
168 |
169 | /**
170 | * @title Pausable
171 | * @dev Base contract which allows children to implement an emergency stop mechanism.
172 | */
173 | contract Pausable is Ownable {
174 | event Pause();
175 | event Unpause();
176 |
177 | bool public paused = false;
178 |
179 |
180 | /**
181 | * @dev Modifier to make a function callable only when the contract is not paused.
182 | */
183 | modifier whenNotPaused() {
184 | require(!paused);
185 | _;
186 | }
187 |
188 | /**
189 | * @dev Modifier to make a function callable only when the contract is paused.
190 | */
191 | modifier whenPaused() {
192 | require(paused);
193 | _;
194 | }
195 |
196 | /**
197 | * @dev called by the owner to pause, triggers stopped state
198 | */
199 | function pause() onlyOwner whenNotPaused public {
200 | paused = true;
201 | Pause();
202 | }
203 |
204 | /**
205 | * @dev called by the owner to unpause, returns to normal state
206 | */
207 | function unpause() onlyOwner whenPaused public {
208 | paused = false;
209 | Unpause();
210 | }
211 | }
212 | ```
213 |
214 | - `modifier` is used to define a reusable modifier function. A modifier is a special function that can be used to modify the behavior of a function, it can be added to the function definition to perform some logic checks or modifications on the function before or after the function is executed. Using modifiers can simplify your code, improve code readability, and reduce repetitive logic in your code.
215 | - `event` is a special type in Solidity used to trigger notifications inside smart contracts. Events are a lightweight communication mechanism for making notifications within smart contracts and providing data to external applications. An application can listen to events and perform some actions when the event is triggered. Events are often used to record important activities and state changes in smart contracts so that applications can respond to these changes.
216 | - `public` is a function access modifier in Solidity. Functions declared with the public keyword can be called by anyone, including addresses inside and outside the contract. State variables declared public can be read by anyone inside or outside the contract. It should be noted that public functions may affect the state of the contract, so security and logical correctness need to be carefully considered when writing public functions.
217 | - The underscore `_` is often used as a placeholder to denote the position of a function or modifier parameter. In the function or modifier definition, the position of the underscore `_` will be replaced by the actual parameter. For example, here's a simple example using underscores:
218 | - Require is an exception handling mechanism, which is used to check whether certain conditions are met during function execution. If the conditions are not met, the function execution is terminated and all states during the execution process are restored to the state before the function call. `
219 | - The is keyword is used to indicate inheritance
220 |
221 |
222 |
223 |
224 |
225 | ```solidity
226 |
227 | /**
228 | * @title ERC20Basic
229 | * @dev Simpler version of ERC20 interface
230 | * @dev see https://github.com/ethereum/EIPs/issues/20
231 | */
232 | contract ERC20Basic {
233 | uint public _totalSupply;
234 | function totalSupply() public constant returns (uint);
235 | function balanceOf(address who) public constant returns (uint);
236 | function transfer(address to, uint value) public;
237 | event Transfer(address indexed from, address indexed to, uint value);
238 | }
239 |
240 | /**
241 | * @title ERC20 interface
242 | * @dev see https://github.com/ethereum/EIPs/issues/20
243 | */
244 | contract ERC20 is ERC20Basic {
245 | function allowance(address owner, address spender) public constant returns (uint);
246 | function transferFrom(address from, address to, uint value) public;
247 | function approve(address spender, uint value) public;
248 | event Approval(address indexed owner, address indexed spender, uint value);
249 | }
250 |
251 | /**
252 | * @title Basic token
253 | * @dev Basic version of StandardToken, with no allowances.
254 | */
255 | contract BasicToken is Ownable, ERC20Basic {
256 | using SafeMath for uint;
257 |
258 | mapping(address => uint) public balances;
259 |
260 | // additional variables for use if transaction fees ever became necessary
261 | uint public basisPointsRate = 0;
262 | uint public maximumFee = 0;
263 |
264 | /**
265 | * @dev Fix for the ERC20 short address attack.
266 | */
267 | modifier onlyPayloadSize(uint size) {
268 | require(!(msg.data.length < size + 4));
269 | _;
270 | }
271 |
272 | /**
273 | * @dev transfer token for a specified address
274 | * @param _to The address to transfer to.
275 | * @param _value The amount to be transferred.
276 | */
277 | function transfer(address _to, uint _value) public onlyPayloadSize(2 * 32) {
278 | uint fee = (_value.mul(basisPointsRate)).div(10000);
279 | if (fee > maximumFee) {
280 | fee = maximumFee;
281 | }
282 | uint sendAmount = _value.sub(fee);
283 | balances[msg.sender] = balances[msg.sender].sub(_value);
284 | balances[_to] = balances[_to].add(sendAmount);
285 | if (fee > 0) {
286 | balances[owner] = balances[owner].add(fee);
287 | Transfer(msg.sender, owner, fee);
288 | }
289 | Transfer(msg.sender, _to, sendAmount);
290 | }
291 |
292 | /**
293 | * @dev Gets the balance of the specified address.
294 | * @param _owner The address to query the the balance of.
295 | * @return An uint representing the amount owned by the passed address.
296 | */
297 | function balanceOf(address _owner) public constant returns (uint balance) {
298 | return balances[_owner];
299 | }
300 |
301 | }
302 |
303 | /**
304 | * @title Standard ERC20 token
305 | *
306 | * @dev Implementation of the basic standard token.
307 | * @dev https://github.com/ethereum/EIPs/issues/20
308 | * @dev Based oncode by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
309 | */
310 | contract StandardToken is BasicToken, ERC20 {
311 |
312 | mapping (address => mapping (address => uint)) public allowed;
313 |
314 | uint public constant MAX_UINT = 2**256 - 1;
315 |
316 | /**
317 | * @dev Transfer tokens from one address to another
318 | * @param _from address The address which you want to send tokens from
319 | * @param _to address The address which you want to transfer to
320 | * @param _value uint the amount of tokens to be transferred
321 | */
322 | function transferFrom(address _from, address _to, uint _value) public onlyPayloadSize(3 * 32) {
323 | var _allowance = allowed[_from][msg.sender];
324 |
325 | // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met
326 | // if (_value > _allowance) throw;
327 |
328 | uint fee = (_value.mul(basisPointsRate)).div(10000);
329 | if (fee > maximumFee) {
330 | fee = maximumFee;
331 | }
332 | if (_allowance < MAX_UINT) {
333 | allowed[_from][msg.sender] = _allowance.sub(_value);
334 | }
335 | uint sendAmount = _value.sub(fee);
336 | balances[_from] = balances[_from].sub(_value);
337 | balances[_to] = balances[_to].add(sendAmount);
338 | if (fee > 0) {
339 | balances[owner] = balances[owner].add(fee);
340 | Transfer(_from, owner, fee);
341 | }
342 | Transfer(_from, _to, sendAmount);
343 | }
344 |
345 | /**
346 | * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
347 | * @param _spender The address which will spend the funds.
348 | * @param _value The amount of tokens to be spent.
349 | */
350 | function approve(address _spender, uint _value) public onlyPayloadSize(2 * 32) {
351 |
352 | // To change the approve amount you first have to reduce the addresses`
353 | // allowance to zero by calling `approve(_spender, 0)` if it is not
354 | // already 0 to mitigate the race condition described here:
355 | // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
356 | require(!((_value != 0) && (allowed[msg.sender][_spender] != 0)));
357 |
358 | allowed[msg.sender][_spender] = _value;
359 | Approval(msg.sender, _spender, _value);
360 | }
361 |
362 | /**
363 | * @dev Function to check the amount of tokens than an owner allowed to a spender.
364 | * @param _owner address The address which owns the funds.
365 | * @param _spender address The address which will spend the funds.
366 | * @return A uint specifying the amount of tokens still available for the spender.
367 | */
368 | function allowance(address _owner, address _spender) public constant returns (uint remaining) {
369 | return allowed[_owner][_spender];
370 | }
371 |
372 | }
373 |
374 | contract UpgradedStandardToken is StandardToken{
375 | // those methods are called by the legacy contract
376 | // and they must ensure msg.sender to be the contract address
377 | function transferByLegacy(address from, address to, uint value) public;
378 | function transferFromByLegacy(address sender, address from, address spender, uint value) public;
379 | function approveByLegacy(address from, address spender, uint value) public;
380 | }
381 | ```
382 |
383 | In Solidity, when defining a function, you can first declare information such as the name, parameters, and return value type of the function, without having to implement the function body immediately. Such a function is called a function signature (Function Signature).
384 |
385 | The `using SafeMath for uint;` statement is used to apply the safe math functions in the `SafeMath` library to the data of type `uint`. This means that in `uint` type data, you can use `add`, `sub`, `mul`, `div` and other safe mathematical operation functions instead of native operators, so as to prevent mathematical overflow or underflow, etc. question.
386 |
387 | In Solidity, `msg.sender` is a global variable that represents the address of the account that calls the current contract function. In Ethereum, each transaction has a sender (Sender), `msg.sender` is the sender address of the current transaction.
388 |
389 | `msg.sender` can be used to verify whether the user calling the contract function has the permission to execute the function. For example, if the contract function only allows the owner of the contract to execute, you can use `require(msg.sender == owner)` inside the function to verify whether the caller is the owner of the contract, and if not, an exception will be thrown, Function execution terminates.
390 |
391 |
392 |
393 | Suppose A wants to trade with B, and the exchange is C, then the transaction process is roughly as follows:
394 |
395 | 1. A submits an order to buy tokens on exchange C.
396 | 2. C generates a new order number and requests A to authorize the token transfer.
397 | 3. A calls the `approve` function of the token contract it holds, and authorizes a certain amount of tokens to C, so that C can transfer tokens on behalf of A.
398 | 4. A sends the authorized order number and related information to C.
399 | 5. B submits an order to sell tokens on exchange C.
400 | 6. C generates a new order number and requests token transfer from B.
401 | 7. B calls the `approve` function of the token contract it holds, and authorizes a certain amount of tokens to C, so that C can transfer tokens on behalf of B.
402 | 8. B sends the authorized order number and related information to C.
403 | 9. C calls the `transferFrom` function of the token contract according to the order number and authorization information, transfers the token from account A to account B, and draws a certain percentage of handling fees.
404 | 10. C updates the order status and notifies A and B that the order has been completed.
405 |
406 | In this transaction process, both A and B need to call the `approve` function to authorize C to transfer tokens on their behalf. C needs to call the `transferFrom` function to realize the token transfer and extract the handling fee. Since the proxy account can only call the `transferFrom` function after being authorized, the security and trustworthiness of the token transfer process can be ensured.
407 |
408 |
409 |
410 | Note that this means that C is trusted.
411 |
412 | ```solidity
413 | contract BlackList is Ownable, BasicToken {
414 |
415 | /////// Getters to allow the same blacklist to be used also by other contracts (including upgraded Tether) ///////
416 | function getBlackListStatus(address _maker) external constant returns (bool) {
417 | return isBlackListed[_maker];
418 | }
419 |
420 | function getOwner() external constant returns (address) {
421 | return owner;
422 | }
423 |
424 | mapping (address => bool) public isBlackListed;
425 |
426 | function addBlackList (address _evilUser) public onlyOwner {
427 | isBlackListed[_evilUser] = true;
428 | AddedBlackList(_evilUser);
429 | }
430 |
431 | function removeBlackList (address _clearedUser) public onlyOwner {
432 | isBlackListed[_clearedUser] = false;
433 | RemovedBlackList(_clearedUser);
434 | }
435 |
436 | function destroyBlackFunds (address _blackListedUser) public onlyOwner {
437 | require(isBlackListed[_blackListedUser]);
438 | uint dirtyFunds = balanceOf(_blackListedUser);
439 | balances[_blackListedUser] = 0;
440 | _totalSupply -= dirtyFunds;
441 | DestroyedBlackFunds(_blackListedUser, dirtyFunds);
442 | }
443 |
444 | event DestroyedBlackFunds(address _blackListedUser, uint _balance);
445 |
446 | event AddedBlackList(address _user);
447 |
448 | event RemovedBlackList(address _user);
449 |
450 | }
451 | ```
452 |
453 | - `external`: Indicates that the function can only be called from outside the contract, not inside the contract. Usually used in public functions to provide the external interface of the contract.
454 | - `constant`: Indicates that the function will not modify the state variables of the contract, nor will it generate any transaction fees, but just read the value of the contract state and return it. Such functions are also often referred to as "view functions" or "pure functions".
455 |
456 | In Solidity, `external` and `constant` can modify a function at the same time, indicating that the function is not only a function that can only be called from outside the contract, but also a pure function that does not modify the state of the contract. This kind of function is usually used to query the value of the contract state without modifying the state.
457 |
458 | Annotating a function helps the compiler with code optimization and error checking, but it doesn't affect the actual gas cost. When you call a function in a contract, you need to pay the gas fee for the function to execute, regardless of whether the function is marked or not.
459 |
460 |
461 |
462 |
463 |
464 | ```solidity
465 | contract TetherToken is Pausable, StandardToken, BlackList {
466 |
467 | string public name;
468 | string public symbol;
469 | uint public decimals;
470 | address public upgradedAddress;
471 | bool public deprecated;
472 |
473 | // The contract can be initialized with a number of tokens
474 | // All the tokens are deposited to the owner address
475 | //
476 | // @param _balance Initial supply of the contract
477 | // @param _name Token Name
478 | // @param _symbol Token symbol
479 | // @param _decimals Token decimals
480 | function TetherToken(uint _initialSupply, string _name, string _symbol, uint _decimals) public {
481 | _totalSupply = _initialSupply;
482 | name = _name;
483 | symbol = _symbol;
484 | decimals = _decimals;
485 | balances[owner] = _initialSupply;
486 | deprecated = false;
487 | }
488 |
489 | // Forward ERC20 methods to upgraded contract if this one is deprecated
490 | function transfer(address _to, uint _value) public whenNotPaused {
491 | require(!isBlackListed[msg.sender]);
492 | if (deprecated) {
493 | return UpgradedStandardToken(upgradedAddress).transferByLegacy(msg.sender, _to, _value);
494 | } else {
495 | return super.transfer(_to, _value);
496 | }
497 | }
498 |
499 | // Forward ERC20 methods to upgraded contract if this one is deprecated
500 | function transferFrom(address _from, address _to, uint _value) public whenNotPaused {
501 | require(!isBlackListed[_from]);
502 | if (deprecated) {
503 | return UpgradedStandardToken(upgradedAddress).transferFromByLegacy(msg.sender, _from, _to, _value);
504 | } else {
505 | return super.transferFrom(_from, _to, _value);
506 | }
507 | }
508 |
509 | // Forward ERC20 methods to upgraded contract if this one is deprecated
510 | function balanceOf(address who) public constant returns (uint) {
511 | if (deprecated) {
512 | return UpgradedStandardToken(upgradedAddress).balanceOf(who);
513 | } else {
514 | return super.balanceOf(who);
515 | }
516 | }
517 |
518 | // Forward ERC20 methods to upgraded contract if this one is deprecated
519 | function approve(address _spender, uint _value) public onlyPayloadSize(2 * 32) {
520 | if (deprecated) {
521 | return UpgradedStandardToken(upgradedAddress).approveByLegacy(msg.sender, _spender, _value);
522 | } else {
523 | return super.approve(_spender, _value);
524 | }
525 | }
526 |
527 | // Forward ERC20 methods to upgraded contract if this one is deprecated
528 | function allowance(address _owner, address _spender) public constant returns (uint remaining) {
529 | if (deprecated) {
530 | return StandardToken(upgradedAddress).allowance(_owner, _spender);
531 | } else {
532 | return super.allowance(_owner, _spender);
533 | }
534 | }
535 |
536 | // deprecate current contract in favour of a new one
537 | function deprecate(address _upgradedAddress) public onlyOwner {
538 | deprecated = true;
539 | upgradedAddress = _upgradedAddress;
540 | Deprecate(_upgradedAddress);
541 | }
542 |
543 | // deprecate current contract if favour of a new one
544 | function totalSupply() public constant returns (uint) {
545 | if (deprecated) {
546 | return StandardToken(upgradedAddress).totalSupply();
547 | } else {
548 | return _totalSupply;
549 | }
550 | }
551 |
552 | // Issue a new amount of tokens
553 | // these tokens are deposited into the owner address
554 | //
555 | // @param _amount Number of tokens to be issued
556 | function issue(uint amount) public onlyOwner {
557 | require(_totalSupply + amount > _totalSupply);
558 | require(balances[owner] + amount > balances[owner]);
559 |
560 | balances[owner] += amount;
561 | _totalSupply += amount;
562 | Issue(amount);
563 | }
564 |
565 | // Redeem tokens.
566 | // These tokens are withdrawn from the owner address
567 | // if the balance must be enough to cover the redeem
568 | // or the call will fail.
569 | // @param _amount Number of tokens to be issued
570 | function redeem(uint amount) public onlyOwner {
571 | require(_totalSupply >= amount);
572 | require(balances[owner] >= amount);
573 |
574 | _totalSupply -= amount;
575 | balances[owner] -= amount;
576 | Redeem(amount);
577 | }
578 |
579 | function setParams(uint newBasisPoints, uint newMaxFee) public onlyOwner {
580 | // Ensure transparency by hardcoding limit beyond which fees can never be added
581 | require(newBasisPoints < 20);
582 | require(newMaxFee < 50);
583 |
584 | basisPointsRate = newBasisPoints;
585 | maximumFee = newMaxFee.mul(10**decimals);
586 |
587 | Params(basisPointsRate, maximumFee);
588 | }
589 |
590 | // Called when new token are issued
591 | event Issue(uint amount);
592 |
593 | // Called when tokens are redeemed
594 | event Redeem(uint amount);
595 |
596 | // Called when contract is deprecated
597 | event Deprecate(address newAddress);
598 |
599 | // Called if contract ever adds fees
600 | event Params(uint feeBasisPoints, uint maxFee);
601 | }
602 | ```
--------------------------------------------------------------------------------