20230311區(qū)塊鏈基礎(chǔ)及eth鏈特性和Solidity特性

Blockchain Basics 區(qū)塊鏈基礎(chǔ)

Blockchains as a concept are not too hard to understand for programmers. The reason is that most of the complications (mining, hashing, elliptic-curve cryptography, peer-to-peer networks, etc.) are just there to provide a certain set of features and promises for the platform.

Once you accept these features as given, you do not have to worry about the underlying technology - or do you have to know how Amazon’s AWS works internally in order to use it?

對于程序員來說,區(qū)塊鏈的概念并不是特別難理解, 原因就是這些所有的問題(挖礦,哈希,橢圓曲線加密,點對點網(wǎng)絡(luò)等等)對于他們來說就是提供了一個特定集合的特性以及預期的平臺.

一點你接受了上述這些特性,你就沒有必要去擔心這些底層的技術(shù)細節(jié),正如你去使用aws的時候不需要關(guān)系亞馬遜aws的內(nèi)部工作原理一樣.

Transaction

A blockchain is a globally shared, transactional database. This means that everyone can read entries in the database just by participating in the network. If you want to change something in the database, you have to create a so-called transaction which has to be accepted by all others. The word transaction implies that the change you want to make (assume you want to change two values at the same time) is either not done at all or completely applied. Furthermore, while your transaction is being applied to the database, no other transaction can alter it.

As an example, imagine a table that lists the balances of all accounts in an electronic currency. If a transfer from one account to another is requested, the transactional nature of the database ensures that if the amount is subtracted from one account, it is always added to the other account. If due to whatever reason, adding the amount to the target account is not possible, the source account is also not modified.

Furthermore, a transaction is always cryptographically signed by the sender (creator). This makes it straightforward to guard access to specific modifications of the database. In the example of the electronic currency, a simple check ensures that only the person holding the keys to the account can transfer money from it.

區(qū)塊鏈是一個全局共享的事務型數(shù)據(jù)庫. 這就意味著所有人都可以通過加入到這個網(wǎng)絡(luò)中來訪問這個數(shù)據(jù)庫. 如果你想改變這個數(shù)據(jù)庫的某個東西,那么你必須要創(chuàng)建一個必須為其他所有人所接受的稱之為事務的東西. 事務這個詞意味著你想做出的改變(假設(shè)你想在同一時間變更兩個值)要么沒成功,要么完全成功. 此外,一旦你的事務在這個數(shù)據(jù)庫中生效了,那么就沒有其他事務可以修改它.

舉個例子吧, 想象一下在一個電子貨幣系統(tǒng)重,你列出了所有賬戶的余額.? 如果有一筆轉(zhuǎn)賬請求發(fā)起, 那么這個數(shù)據(jù)庫事務性的特性就保證了,

一個賬戶減少多少金額,那么這部分金額就會相應的增加到另一個賬戶中. 如果由于任何原因?qū)е铝嗽黾咏痤~到特定賬戶不可能,那么原賬戶也將不會修改.

更近一步的,每一個事務總是由發(fā)起者或者說創(chuàng)建者通過密碼簽名的,這就直接了當?shù)谋WC對數(shù)據(jù)庫的特定修改是安全的.? 在電子貨幣的案例中,一個簡單的驗證確保了僅僅只有持有key的人可以從當前賬戶轉(zhuǎn)賬.

Blocks 區(qū)塊

One major obstacle to overcome is what (in Bitcoin terms) is called a “double-spend attack”: What happens if two transactions exist in the network that both want to empty an account? Only one of the transactions can be valid, typically the one that is accepted first. The problem is that “first” is not an objective term in a peer-to-peer network.

一個主要需要克服的障礙就是(用比特幣的術(shù)語來說)稱之為雙花工具:如果兩個交易并存在同一個網(wǎng)絡(luò)中,并且他們都想要清空一個賬號? 而只有一個事務是合法的,

典型的做法是,第一個被接受的就是合法的. 但是問題在于在點對點網(wǎng)絡(luò)中第一個被接受的并不是一個客觀的術(shù)語

The abstract answer to this is that you do not have to care. A globally accepted order of the transactions will be selected for you, solving the conflict. The transactions will be bundled into what is called a “block” and then they will be executed and distributed among all participating nodes. If two transactions contradict each other, the one that ends up being second will be rejected and not become part of the block.

這個抽象的答案是你不需要去關(guān)注的東西.? 一個全局所接受的事務順序?qū)槟阕龀鲞x擇,解決這個沖突. 所有的交易會被打包放入到區(qū)塊中,然后這個區(qū)塊會被所有參與的節(jié)點執(zhí)行并且分發(fā). 如果兩個交易彼此沖突,那么隨后被執(zhí)行的那個事務將會被拒絕,不會成為區(qū)塊的一部分.

These blocks form a linear sequence in time, and that is where the word “blockchain” derives from. Blocks are added to the chain at regular intervals, although these intervals may be subject to change in the future. For the most up-to-date information, it is recommended to monitor the network, for example, on Etherscan.

這些區(qū)塊隨著時間組織的線性序列,這也就是區(qū)塊鏈一詞的來源. 這些區(qū)塊會被間歇性的加入到這個鏈條中, 盡管這些間隔時間在未來會被重新修改. 如果想獲取最新的信息

建議監(jiān)控整個網(wǎng)絡(luò),比如使用Etherscan.

As part of the “order selection mechanism” (which is called “mining”) it may happen that blocks are reverted from time to time, but only at the “tip” of the chain. The more blocks are added on top of a particular block, the less likely this block will be reverted. So it might be that your transactions are reverted and even removed from the blockchain, but the longer you wait, the less likely it will be.

作為順序選擇機制的一部分(也叫挖礦),也可能發(fā)生隨著時間區(qū)塊被回滾,但是僅僅出現(xiàn)在小鏈中. 對于一個特定的塊來說,越多的塊被加入到它,那么這個區(qū)塊回歸的概率就越小. 因此可能你的交易也會被回滾并且從區(qū)塊鏈中移除,但是只要你等的時間越長,這種可能性就越小.

The Ethereum Virtual Machine

The Ethereum Virtual Machine or EVM is the runtime environment for smart contracts in Ethereum. It is not only sandboxed but actually completely isolated, which means that code running inside the EVM has no access to network, filesystem or other processes. Smart contracts even have limited access to other smart contracts.

EVM 是在以太坊網(wǎng)絡(luò)中智能合約的運行環(huán)境.它不僅僅是沙河保護的并且是事實上的完全隔離的, 也就是說代碼運行在evm內(nèi),不需要訪問網(wǎng)絡(luò),文件系統(tǒng)或者其他進程.

甚至是智能合約也僅僅是可以有限的訪問其他智能合約.

Accounts

There are two kinds of accounts in Ethereum which share the same address space: External accounts that are controlled by public-private key pairs (i.e. humans) and contract accounts which are controlled by the code stored together with the account.

賬戶的概念, 在以太坊網(wǎng)絡(luò)中有兩種類型的賬戶,共享共同的地址空間: 由公鑰私鑰對控制的外部賬號(比如人),以及由跟代碼存儲在一起的賬戶共同控制的合約賬戶.

The address of an external account is determined from the public key while the address of a contract is determined at the time the contract is created (it is derived from the creator address and the number of transactions sent from that address, the so-called “nonce”).

外部地址又公鑰決定,而合約地址是由合約創(chuàng)建的時候確定的(它取決于創(chuàng)建者地址,以及從這個地址發(fā)出的交易數(shù)量,或者我們稱之為nonce)

Regardless of whether or not the account stores code, the two types are treated equally by the EVM.

不管這賬戶是否存儲了代碼,這兩種類型的賬號被EVM對等的處理

Every account has a persistent key-value store mapping 256-bit words to 256-bit words called storage.

每一個賬戶有一個永久性的鍵值對的存儲映射,將256位字符映射到256位字符,我們稱之為存儲.

Furthermore, every account has a balance in Ether (in “Wei” to be exact, 1 ether is 10**18 wei) which can be modified by sending transactions that include Ether.

此外,每一個賬號都會有一個以ether數(shù)量為計算的余額(確切的說是WEI,1eth=10^18),這個余額可以通過發(fā)送包含eth交易的方式進行變更.

Transactions 事務

A transaction is a message that is sent from one account to another account (which might be the same or empty, see below). It can include binary data (which is called “payload”) and Ether.

一個事務就是一個賬戶發(fā)給另一個賬號的信息(當然另一個賬戶可以是自己,也可以是為空,具體見下文) 這筆事務也可以包含二進制數(shù)據(jù)(我們稱之為payload收費載重)和ether代幣.

If the target account contains code, that code is executed and the payload is provided as input data.

如果目標賬戶包好了代碼,那么這個代碼將被執(zhí)行,同時payload將被視為輸入數(shù)據(jù).

If the target account is not set (the transaction does not have a recipient or the recipient is set to null), the transaction creates a new contract.

如果目標賬號沒有設(shè)置(也就是這筆事務沒有收款人,或者收款人設(shè)置為空),那么這筆事務將創(chuàng)建一個新的合約.

As already mentioned, the address of that contract is not the zero address but an address derived from the sender and its number of transactions sent (the “nonce”).

正如前文所說的那樣,這個合約地址不是一個零地址,但是它是由發(fā)送方地址和發(fā)送方發(fā)送的交易數(shù)量決定

The payload of such a contract creation transaction is taken to be EVM bytecode and executed. The output data of this execution is permanently stored as the code of the contract.

這個合約創(chuàng)建的事務的payload,被拿到EVM字節(jié)碼并且被執(zhí)行. 本次執(zhí)行的輸出數(shù)據(jù)被永久性的存儲為合約的代碼.

This means that in order to create a contract, you do not send the actual code of the contract, but in fact code that returns that code when executed.

那么也就意味著,為了創(chuàng)建一個合約,你不需要發(fā)送合約的實際代碼,但是事實上這個代碼就是執(zhí)行返回的代碼.

Note

While a contract is being created, its code is still empty. Because of that, you should not call back into the contract under construction until its constructor has finished executing.

請注意,當一個合約被創(chuàng)建的時候,其代碼依舊是空的, 因此,你不應該返回調(diào)用這個合約,當這個合約正在創(chuàng)建過程中,直到它的構(gòu)造函數(shù)已經(jīng)完成執(zhí)行的時候.

GAS

Upon creation, each transaction is charged with a certain amount of gas that has to be paid for by the originator of the transaction (tx.origin). While the EVM executes the transaction, the gas is gradually depleted according to specific rules. If the gas is used up at any point (i.e. it would be negative), an out-of-gas exception is triggered, which ends execution and reverts all modifications made to the state in the current call frame.

當創(chuàng)建的時候,每一筆事務都需要由事務的發(fā)起者去支付特定數(shù)量的gas. 當EVM執(zhí)行這筆交易時,gas是根據(jù)特定的規(guī)則逐漸被消耗的. 如果這個gas在任何一個節(jié)點被使用完(例如gas為負數(shù)了),那么就會觸發(fā)gas不足的異常, 這樣執(zhí)行將終止,在當前調(diào)用框架中所有對于狀態(tài)的所有修改都將被回滾.

This mechanism incentivizes economical use of EVM execution time and also compensates EVM executors (i.e. miners / stakers) for their work. Since each block has a maximum amount of gas, it also limits the amount of work needed to validate a block.

這個機制就鼓勵人民經(jīng)濟性的使用evm執(zhí)行時間,同時也獎勵了evm的執(zhí)行者(比如礦工和質(zhì)押人)的工作,由于每一個塊都有一個最高的gas金額,因此也就限制了

驗證一個塊所需要的工作額.

The gas price is a value set by the originator of the transaction, who has to pay gas_price * gas up front to the EVM executor. If some gas is left after execution, it is refunded to the transaction originator. In case of an exception that reverts changes, already used up gas is not refunded.

gas price是由交易發(fā)起者設(shè)定的一個值, 這個交易執(zhí)行者必須提前支付 gas price* gas數(shù)量的eth給evm 的執(zhí)行者. 如果在執(zhí)行完之后還有一些gas剩余,那么將會返回給交易發(fā)起者.而當異常情況,交易回滾了,那么已經(jīng)花費的gas是不會被退回的.

Since EVM executors can choose to include a transaction or not, transaction senders cannot abuse the system by setting a low gas price.

因為EVM執(zhí)行者可以選擇包含某個交易或者不包含, 交易發(fā)起者不能通過設(shè)置低額的gas price去虐待凌辱這個系統(tǒng).

Storage, Memory and the Stack

The Ethereum Virtual Machine has three areas where it can store data: storage, memory and the stack.

evm有三個區(qū)域可以存儲數(shù)據(jù): 存儲,內(nèi)存以及 棧

Each account has a data area called storage, which is persistent between function calls and transactions. Storage is a key-value store that maps 256-bit words to 256-bit words. It is not possible to enumerate storage from within a contract, it is comparatively costly to read, and even more to initialise and modify storage. Because of this cost, you should minimize what you store in persistent storage to what the contract needs to run. Store data like derived calculations, caching, and aggregates outside of the contract. A contract can neither read nor write to any storage apart from its own.

每一個賬戶都有一個數(shù)據(jù)區(qū)域,稱之為存儲,這個區(qū)域永久性的存在于函數(shù)調(diào)用和事務之間. 存儲是一個鍵值對,存儲的是一個256bit的字符 key-value對.

在一個合約內(nèi)部是不能去枚舉所有的數(shù)據(jù)存儲.? 相比而已,讀取是非常耗費gas費的, 而初始化和修改存儲區(qū)的數(shù)據(jù)更昂貴.? 由于這個花費的問題, 你應該最小化

你想存入到永久存儲中的數(shù)據(jù). 只將必要的數(shù)據(jù)放到合約中.? 存儲數(shù)據(jù)比如派生出的計算,緩存,以及聚合等盡量放在合約之外.

一個合約既不能讀也不能寫除自己之外其他合約的存儲數(shù)據(jù).

The second data area is called memory, of which a contract obtains a freshly cleared instance for each message call. Memory is linear and can be addressed at byte level, but reads are limited to a width of 256 bits, while writes can be either 8 bits or 256 bits wide. Memory is expanded by a word (256-bit), when accessing (either reading or writing) a previously untouched memory word (i.e. any offset within a word). At the time of expansion, the cost in gas must be paid. Memory is more costly the larger it grows (it scales quadratically). 內(nèi)存區(qū)域是按照一個字(256位)進行擴展的, 當進行讀寫訪問之前的一個為加倉的內(nèi)存字(也就是位移長度是一個字256位),隨著時間的延長,gas也必須是要支付的, 內(nèi)存對于gas的消費是隨著大小而增長的(指數(shù)級增長)

第二部分的數(shù)據(jù)區(qū)域我們稱之為內(nèi)存, 針對合約的每次消息的調(diào)用,都會獲取一份干凈新鮮的內(nèi)存區(qū)域. 內(nèi)存區(qū)域是是線性連貫的, 可以通過字節(jié)級別進行尋址到.

但是讀取只能讀256位比特寬的數(shù)據(jù), 可以讀8位,或者256位比特寬.

The EVM is not a register machine but a stack machine, so all computations are performed on a data area called the stack. It has a maximum size of 1024 elements and contains words of 256 bits. Access to the stack is limited to the top end in the following way: It is possible to copy one of the topmost 16 elements to the top of the stack or swap the topmost element with one of the 16 elements below it. All other operations take the topmost two (or one, or more, depending on the operation) elements from the stack and push the result onto the stack. Of course it is possible to move stack elements to storage or memory in order to get deeper access to the stack, but it is not possible to just access arbitrary elements deeper in the stack without first removing the top of the stack.

EVM不是一個注冊機,而是一個棧機, 因此所有的計算是在數(shù)據(jù)區(qū)域進行的,我們稱之為棧. 它有最大1024個元素,包含256位的字.

訪問棧限制為訪問最頂端. 通過如下方式. 可以復制棧最頂端16個元素中的一個到棧的最頂端,或者將最頂端元素的十六個元素和下方的進行交換.

所有其他的操作,從棧中取這最頂端的兩個(或者一個或者更多,取決于操作)元素,然后將結(jié)果推送到棧中,當然也可以將棧中的元素存入到存儲中或者內(nèi)存中,用于訪問更深處的棧, 但是不能實現(xiàn)隨機訪問棧中的深層元素,而不需要將第一個元素移除棧頂.

Instruction Set 指令集合

The instruction set of the EVM is kept minimal in order to avoid incorrect or inconsistent implementations which could cause consensus problems. All instructions operate on the basic data type, 256-bit words or on slices of memory (or other byte arrays). The usual arithmetic, bit, logical and comparison operations are present. Conditional and unconditional jumps are possible. Furthermore, contracts can access relevant properties of the current block like its number and timestamp.

For a complete list, please see the list of opcodes as part of the inline assembly documentation.

EVM的指令集保持著最小的狀態(tài),是為了避免不正確或者不一致的實現(xiàn),從而導致共識問題. 所有的指令操作都是基于基本的數(shù)據(jù)類型. 256位的字或者內(nèi)存中的一個片段(或者其他字節(jié)數(shù)組), 正常的算術(shù),bit 邏輯和比較操作都是. 條件和無條件的跳躍是可能的. 此外 合約可以訪問當前區(qū)塊中的相關(guān)屬性,比如塊的編號和時間戳.

想看完整的指令列表,請查閱內(nèi)聯(lián)匯編文檔的操作碼部分.

Message Calls

Contracts can call other contracts or send Ether to non-contract accounts by the means of message calls. Message calls are similar to transactions, in that they have a source, a target, data payload, Ether, gas and return data. In fact, every transaction consists of a top-level message call which in turn can create further message calls.

消息調(diào)用

合約可以調(diào)用其他合約或者發(fā)送eth給其他非合約賬戶,通過消息調(diào)用的方式.? 消息調(diào)用跟事務是非常類似的,在這個場景中,有源頭賬戶,目標賬戶,數(shù)據(jù)載重,eth

gas費以及返回數(shù)據(jù). 實際上,每一個事務都是有 頂級的消息調(diào)用構(gòu)成,并隨之反過來創(chuàng)建更遠期的消息調(diào)用.

A contract can decide how much of its remaining gas should be sent with the inner message call and how much it wants to retain. If an out-of-gas exception happens in the inner call (or any other exception), this will be signaled by an error value put onto the stack. In this case, only the gas sent together with the call is used up. In Solidity, the calling contract causes a manual exception by default in such situations, so that exceptions “bubble up” the call stack.

一個合約可以決定多少留存的gas費應該通過內(nèi)聯(lián)消息調(diào)用的方式發(fā)送,以及他想保留多少. 如果gas費不足的異常發(fā)生在內(nèi)聯(lián)調(diào)用中(或者其他的異常情況),這個異常會通過

erro的方式推送到棧中. 在這種情況下,只有跟隨調(diào)用的gas費被使用完. 在Solidity中, 剛才的那種情況下,正在調(diào)用的合約中會引發(fā)一個手動的異常,那就是調(diào)用棧沸騰異常.

As already said, the called contract (which can be the same as the caller) will receive a freshly cleared instance of memory and has access to the call payload - which will be provided in a separate area called the calldata. After it has finished execution, it can return data which will be stored at a location in the caller’s memory preallocated by the caller. All such calls are fully synchronous.

正如我們已經(jīng)說過的那樣,被調(diào)用的合約(同樣的調(diào)用方的合約也一樣)將會收到一個完全干凈新鮮的內(nèi)存實例,可以訪問付費負載,合約提供了一個單獨的數(shù)據(jù),我們稱之為調(diào)用數(shù)據(jù). 當調(diào)用執(zhí)行結(jié)束的時候, 會返回數(shù)據(jù),這個返回數(shù)據(jù)被存儲在調(diào)用方的預分配內(nèi)存中某個地方. 所有的這些操作都是同步的.

Calls are limited to a depth of 1024, which means that for more complex operations, loops should be preferred over recursive calls. Furthermore, only 63/64th of the gas can be forwarded in a message call, which causes a depth limit of a little less than 1000 in practice.

調(diào)用方限制的深度是1024, 這也就意味著對于更加復雜的操作,循環(huán)調(diào)用會比遞歸調(diào)用好. 此外在消息調(diào)用中,只有63/64級的gas可以被轉(zhuǎn)發(fā),這就導致實際上,

可以有最多1000次調(diào)用深度.

Delegatecall and Libraries

委托調(diào)用和庫

There exists a special variant of a message call, named delegatecall which is identical to a message call apart from the fact that the code at the target address is executed in the context (i.e. at the address) of the calling contract and msg.sender and msg.value do not change their values.

在消息調(diào)用中存在一種特殊的變種,我們稱之為 代理調(diào)用,這種調(diào)用跟消息調(diào)用是完全相同的. 唯一的區(qū)別就是目標地址中的代碼被執(zhí)行是在調(diào)用合約的上下文中環(huán)境中(比如地址),以及 msg.sender 和msg.value 并沒有變更它們的值.

This means that a contract can dynamically load code from a different address at runtime. Storage, current address and balance still refer to the calling contract, only the code is taken from the called address.

這也就意味著 合約可以在運行時從不同地址中動態(tài)加載. 存儲區(qū),當前地址,以及余額仍然指向的是調(diào)用的合約, 僅僅只是代碼是從被調(diào)用的地址中取出來的.

This makes it possible to implement the “l(fā)ibrary” feature in Solidity: Reusable library code that can be applied to a contract’s storage, e.g. in order to implement a complex data structure.

這就可以讓Solidity實現(xiàn)庫一樣的特性, 可以重復使用的代碼庫, 可以被應用在一個存儲中,比如 為了實現(xiàn)一個復雜的數(shù)據(jù)結(jié)構(gòu).

Logs

It is possible to store data in a specially indexed data structure that maps all the way up to the block level. This feature called logs is used by Solidity in order to implement events. Contracts cannot access log data after it has been created, but they can be efficiently accessed from outside the blockchain. Since some part of the log data is stored in bloom filters, it is possible to search for this data in an efficient and cryptographically secure way, so network peers that do not download the whole blockchain (so-called “l(fā)ight clients”) can still find these logs.

可以將數(shù)據(jù)存儲在一個專門索引的數(shù)據(jù)結(jié)構(gòu)中,該結(jié)構(gòu)一直映射到塊級別。這個特性在Solidity中稱為日志,用于實現(xiàn)事件.

合約在被創(chuàng)建之后就是不能夠訪問日志數(shù)據(jù), 但是他們可以從區(qū)塊鏈外部高效的訪問到.? 由于部分日志數(shù)據(jù)存儲時采用的是布隆過濾器的方式,

因此可以非常高效的訪問檢索到這部分數(shù)據(jù),并且通過密碼加密的安全方式. 因此輕客戶端網(wǎng)絡(luò)節(jié)點不下載整個區(qū)塊鏈(因此稱為輕客戶端),仍然可以找到這些日志.

Create

Contracts can even create other contracts using a special opcode (i.e. they do not simply call the zero address as a transaction would). The only difference between these create calls and normal message calls is that the payload data is executed and the result stored as code and the caller / creator receives the address of the new contract on the stack.

Deactivate and Self-destruct

The only way to remove code from the blockchain is when a contract at that address performs the selfdestruct operation. The remaining Ether stored at that address is sent to a designated target and then the storage and code is removed from the state. Removing the contract in theory sounds like a good idea, but it is potentially dangerous, as if someone sends Ether to removed contracts, the Ether is forever lost.

將代碼從合約中刪除的唯一方法就是一個合約調(diào)用自己的析構(gòu)函數(shù). 存儲在當前地址上的eth將會被發(fā)送到預設(shè)的目標地址上,同時存儲區(qū)以及代碼從狀態(tài)中移除.

將合約移除聽起來是一個好的注意,但是潛藏著危險. 因為假設(shè)有人將eth發(fā)送到刪除的合約中, eth將永遠的丟失.

If you want to deactivate your contracts, you should instead disable them by changing some internal state which causes all functions to revert. This makes it impossible to use the contract, as it returns Ether immediately.

如果你想失效你的合約,你應該 改變內(nèi)部的狀態(tài)并且會導致所有的函數(shù)回滾從而使得當前合約失效. 這就使得這個合約不能使用,并且將eth立即返回.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容