我理解为什么以太坊主网上的所有节点都必须执行任何改变合约或链内部状态的智能合约函数调用,这一点很重要。(例如,从一个账户转移到另一个账户。(
我想知道的是,如果每个节点都必须执行任何智能合约上调用的每个函数,即使该函数不会导致状态更改,这是否属实。
例如,如果ERC721智能合约具有一个功能";getName(("它只是返回NFT所代表的艺术品的名称,该名称存储在NFT中。假设joe连接到网络,并希望在合约上执行getName((。这是否意味着所有9000个节点最终都会循环执行getName((,即使Joe只需要执行一次?燃气运行成本";getName(("补偿每个节点的运行"0"的开销;getName(("?如果这是真的(每个节点都有报酬(,随着更多节点加入池,天然气会变得更加昂贵吗?
天然气价格高的原因之一是因为每个节点都必须执行智能合约上调用的每个功能,即使是对状态没有影响的功能,效率低下吗?
如果是这样的话,执行一个计算密集但"不必要"的命题似乎是一个非常(并且可能是不必要的(昂贵的命题;纯";(没有副作用(在以太坊上的功能,对吧?
谢谢。为这个可能很天真的问题道歉!
事务(可以进行状态更改,但不需要(和调用(只读,不能进行状态更改(之间有区别。
我将从通话开始,因为它更容易。
当节点执行调用时,它会执行契约函数,该函数很可能从存储器中读取、存储到存储器,然后从存储器中返回。
示例:
string name;
function getName() external view returns (string memory) {
// reads from storage, stores to memory, returns from memory
return name;
}
但它不会向其他节点广播任何信息(例如"我刚刚执行了读取操作"(。即其他节点不执行相同的操作。
在每个节点上执行一次事务。
string name;
function setName(string memory _name) external {
// reads from memory, stores to storage
name = _name;
}
矿工从mempool(等待挖掘的事务列表(中获取事务,在其机器上执行它,执行状态更改,并将事务添加到块中(包括预期的状态更改(。
然后,所有(验证器(节点下载新块,执行事务,并在其端执行相同的状态更改。如果他们发现自己的状态更改与矿工声明的状态更改不匹配,他们会将其广播到网络中,声明可能的无效块。
回答您的问题:
这是否意味着所有9000个节点最终都会循环执行getName((,即使Joe只需要执行一次
如果Joe请求调用,则仅在一个节点(Joe连接到的节点(上执行getName()
。如果他请求一个事务,它将在所有节点上执行。
运行";getName(("补偿每个节点的运行"0"的开销;getName((">
它只补偿(获胜(矿工,后者承担交易费用。更大的tx费用(ETH的总量,而不是汽油价格(补偿了机器需要使用的更大的资源使用量(主要是CPU时间(,与多个";更容易";他们可以使用相同的资源执行的事务。
如果这是真的(每个节点都会得到报酬(,那么随着更多节点加入池,gas会变得更加昂贵吗
并非每个节点都会得到报酬,请参阅上文。
天然气价格高的原因之一是因为每个节点都必须执行智能合约上调用的每个函数,即使是对状态没有影响的函数,效率低下吗
这可能主要是出于经济原因——供应和需求。越多的人希望尽快执行交易,并愿意支付更高的天然气价格,他们就会推高天然气价格。可能他们只是使用了钱包应用程序推荐的价格,这个价格可能高于平均水平。