transaction(可以进行状态更改 - 但不需要)和call(只读,不能进行状态更改)之间存在区别。
我将从通话开始,因为它更容易。
当节点执行调用时,它会执行最有可能从存储读取、存储到内存并从内存返回的合约函数。
例子:
string name;
function getName() external view returns (string memory) {
// reads from storage, stores to memory, returns from memory
return name;
}
但它不会向其他节点广播任何信息(例如“我刚刚执行了读取操作”)。 IE。其他节点不执行相同的操作。
一个事务在每个节点上执行一次。
string name;
function setName(string memory _name) external {
// reads from memory, stores to storage
name = _name;
}
矿工从内存池(等待挖掘的交易列表)中获取交易,在他们的机器上执行它,执行状态更改,并将交易添加到块中(包括预期的状态更改)。
所有(验证者)节点然后下载新块,执行交易,并在其末端执行相同的状态更改。如果他们发现自己的状态更改与矿工声明的状态更改之间不匹配,他们会将其广播到网络中,并声明一个可能的无效块。
回答您的问题:
这是否意味着所有 9,000 个节点最终都会执行 getName(),即使 Joe 只需要执行一次?
如果 Joe 请求调用,getName() 仅在一个节点(Joe 连接到的节点)上执行。如果他请求一个事务,它会在所有节点上执行。
运行“getName()”的 gas 成本是否补偿了每个节点运行“getName()”的开销?
它只补偿收取交易费用的(获胜的)矿工。与它们可以使用相同资源执行的多个“更简单”的交易相比,更大的 tx 费用(ETH 总量,而不是 gas 价格)补偿了机器需要使用的更多资源(主要是 CPU 时间)的使用。
如果这是真的(每个节点都得到报酬),随着更多节点加入池,gas 会变得更加昂贵吗?
并非每个节点都能获得报酬,见上文。
gas 价格高的原因之一是因为每个节点都必须执行智能合约上调用的每个函数的效率低下,即使是那些对状态没有影响的函数?
这可能主要是出于经济原因 - 供求关系。越多的人希望尽快执行交易并愿意支付更高的 gas 价格,他们就会推高 gas 价格。可能他们只是使用钱包应用推荐的价格,这可能高于平均水平。