乙太坊智能合約執行原理
我有一個聽起來可能很愚蠢的問題,但它的理解對我來說至關重要。
比如說,我有一個智能合約,它有一個公共變數和一個用於更改該變數的設置器。如果一個智能合約同時由 2 個地址執行,乙太坊區塊鏈的行為如何?它會為第一個地址執行第一個合約,然後為第二個地址執行它,還是會製作一份合約的“副本”,為第二個地址執行它?是否有這樣的情況,當第二個地址的 setter 函式無法更改變數時,因為該變數已經被第一個地址“使用”了?
這不是一個愚蠢的問題。
將合約視為在不同節點上執行的單獨實例時,這是毫無意義的。EVM 被建模為分佈式狀態機。有一個 EVM 狀態是合乎邏輯的,並且獨立於節點。該協議確保(幾乎)節點最終將在給定點就規範狀態達成一致。
要解決的一個關鍵問題是交易的順序。所有節點都必須對此達成一致,這是就這些交易的影響達成一致的先決條件。由於網路延遲,交易順序存在歧義。這是通過採礦過程解決的。採礦以特定順序產生交易塊。當節點聽到一個區塊時,它們會處理包含的交易,然後將與該區塊編號的其他節點達成一致,也稱為區塊高度。
如果一個智能合約同時由 2 個地址執行,乙太坊區塊鏈的行為如何?
這是不可能的。一切都是由一個外部擁有的賬戶(錢包)簽署交易並將其發送到智能合約(通常是特定功能)開始的。合約並未“執行”,但交易已被提議。
該交易將被探勘。對於由或多或少同時廣播的兩個不同賬戶簽署的兩筆交易的開採順序無法保證。我們可以確定的是,採礦過程將確保其中一個或另一個首先進行。它將在下一個事務開始之前進行全面評估。
它是否會為第一個地址執行第一個合約,然後為第二個地址執行它
它將執行第一個被探勘的,然後是第二個被探勘的。
還是會製作一份契約的“副本”,為第二個地址執行它
每個完整節點上都存在一份“契約副本”。合約是狀態的一部分,用於處理區塊中的交易(如果節點沒有合約副本,如何根據合約處理交易?)。每個完整節點執行每個事務。所有完整節點都知道虛擬機的“狀態”。狀態是唯一合乎邏輯的結論,因為它們都同意區塊鏈中描述的有序交易。
是否有這樣的情況,當第二個地址的 setter 函式無法更改變數時,因為該變數已經被第一個地址“使用”了?
不會。但是,第二筆交易開始時的合約狀態將是第一筆交易的結果。它將在完成後留下的第一個事務的上下文中執行。
這是我拼湊起來的一個簡單範例。想像一下來自多個試圖成為第一的發送者的協同爆發。它僅適用於第一個開采的交易,這與第一次發送的交易不同。事實上,參賽者可以通過使用
gasPrice
.pragma solidity 0.4.25; contract WorksOnce { bool isUsed; event LogLuckyWinner(address sender); function pickMe() public { require(!isUsed); isUsed = true; emit LogLuckyWinner(msg.sender); } }
希望能幫助到你。