区块链上的所有节点都必须执行每个智能合约函数 cal 吗?

use*_*110 4 ethereum solidity

我理解为什么以太坊主网上的所有节点都必须执行任何改变合约或链的内部状态的智能合约函数调用,这一点很重要。(例如,从一个帐户转账到另一个帐户。)

我想知道的是,是否每个节点都必须执行任何智能合约上调用的每个函数,即使该函数不会导致状态更改。

例如,如果 ERC721 智能合约具有函数“getName()”,该函数仅返回 NFT 表示的艺术品的名称,该艺术品存储在 NFt 中。假设 joe 连接到网络,并希望在合约上执行 getName()。这是否意味着所有 9,000 个节点最终都会循环执行 getName(),即使 Joe 只需要执行一次?运行“getName()”的 Gas 成本是否补偿每个节点运行“getName()”的开销?如果这是真的(每个节点都得到报酬),随着更多节点加入池中,gas 会变得更加昂贵吗?

天然气价格高的原因之一是因为每个节点必须执行智能合约上调用的每个函数(即使是那些对状态没有影响的函数)效率低下吗?

如果是这样,在以太坊上执行计算密集型但“纯粹”(无副作用)的功能似乎是一个非常(也许不必要)昂贵的提议,对吗?

谢谢。对于这个可能天真的问题表示歉意!

Pet*_*jda 8

事务(可以进行状态更改 - 但不需要)和调用(只读,不能进行状态更改)之间存在差异。


我将从通话开始,因为这样更容易。

当节点执行调用时,它执行的合约函数很可能从存储中读取,存储到内存中,然后从内存中返回。

例子:

string name;

function getName() external view returns (string memory) {
    // reads from storage, stores to memory, returns from memory
    return name;
}
Run Code Online (Sandbox Code Playgroud)

但它不会向其他节点广播任何信息(例如“我刚刚执行了读取操作”)。即其他节点不执行相同的操作。


一笔交易在每个节点上执行一次。

string name;

function setName(string memory _name) external {
    // reads from memory, stores to storage
    name = _name;
}
Run Code Online (Sandbox Code Playgroud)

矿工从内存池(等待挖掘的交易列表)中获取交易,在自己的机器上执行它,执行状态更改,并将交易添加到块中(包括预期的状态更改)。

然后,所有(验证者)节点下载新块,执行交易,并在其末端执行相同的状态更改。如果他们发现自己的状态更改与矿工声明的状态更改之间不匹配,他们会将其广播到网络中,声明可能是无效块。


回答您的问题:

这是否意味着所有 9,000 个节点最终都会循环执行 getName(),即使 Joe 只需要执行一次?

如果 Joe 请求调用,getName()则仅在一个节点(Joe 连接到的节点)上执行。如果他请求一笔交易,该交易就会在所有节点上执行。

运行“getName()”的 Gas 成本是否补偿每个节点运行“getName()”的开销?

它只补偿(获胜的)矿工,后者收取交易费用。与使用相同资源执行多个“更简单”的交易相比,更大的交易费用(ETH 总量,而不是 Gas 价格)可以补偿机器需要使用的更多资源(主要是 CPU 时间)。

如果这是真的(每个节点都得到报酬),随着更多节点加入池中,gas 会变得更加昂贵吗?

并非每个节点都会获得报酬,见上文。

天然气价格高的原因之一是因为每个节点必须执行智能合约上调用的每个函数(即使是那些对状态没有影响的函数)效率低下吗?

这可能主要是出于经济原因——供给和需求。越多的人想要尽快执行交易并愿意支付更高的 Gas 价格,他们就会将 Gas 价格推得越高。可能他们只是使用钱包应用程序推荐的价格,该价格可能高于平均水平。