
## 简介
基于以太坊虚拟机(EVM)的网络通常可以运行两种类型的节点:一个全节点和一个存档节点。
许多流行网络基于EVM:包括[以太坊](https://learnblockchain.cn/categories/ethereum/) 、Polygon 、[BNB Smart Chain](https://learnblockchain.cn/article/2626)、C-Chain of Avalanche 、Fantom、Harmony等。
全节点和存档节点两者都存储完整的区块链数据,可用于重放网络状态,但区别在于,存档节点另外将每个区块的网络状态存储在一个存档中,可供查询。
这就是简短的解释。
在这篇文章中,我们将深入探讨全节点和存档节点的一些细节、区别和操作实例。
## Geth和Erigon
首先,简单介绍一下节点客户端:
[Go 以太坊](https://github.com/ethereum/go-ethereum)(Geth)是迄今为止最流行的基于EVM的网络的客户端软件,可能在整个区块链领域都是如此。
对于以太坊主网,你可以在[ethernodes crawler data](https://www.ethernodes.org/)查看节点客户端分布。
Chainstack支持使用Geth客户端或[Erigon客户端](https://github.com/ledgerwatch/erigon)(以前是Turbo-Geth)来运行以太坊节点–后者是另一个Go实现客户端,专注于效率,是第二流行的客户端。
在这篇文章中,我们将重点介绍Geth和Erigon在全节点和存档节点模式下的实现。
## 全节点和存档节点
让我们深入了解一下细节:
### **全节点**
– 存储完整的区块链数据。
– 验证所有区块和状态。
– 所有的状态都可以从一个完整的节点重新生成。
一个完整的EVM节点保持区块链的当前状态,并处理读取调用(view)和状态改变的调用(交易)。一个完整的节点会修剪区块链数据,以节省磁盘空间并减少同步时间,但在必要时存储足够的数据来重新计算链上的事件,使得它的运行效率更高,但它也限制请求特定数量的区块的数据(通常为128个区块)。
例如,在以太坊主网上,产生一个新区块的平均时间约为13秒,你只能检索过去28-29分钟的链状态。虽然在理论上,你可以使用一个完整的节点来重新计算所有的中间状态,但这将需要特别长的时间,而且将是非常密集的资源,你的节点可能会耗尽内存而停止。
### 默认的返回状态和 `Missing trie node`的错误
根据所访问的链和所使用的客户端,被限制能访问多少个可用的区块状态有所不同:
– **以太坊**:128个区块
– **Polygon**: 128个区块
– **BNB智能链:** 128个区块
– **Avalanche** C-Chain:32个区块
– **Fantom**: Go Opera客户端不修剪信息,所以在全节点和存档节点之间没有区别。
– **Harmony**: 128个区块
如果你试图查询一个不能从全节点访问的区块,你会收到一个**missing trie node**的错误。
一般来说,收到**missing trie node**的错误意味着你需要一个存档节点。
## 存档节点
– 存储所有保存在全节点中的东西,并建立一个历史状态的档案。
– 他们是配置为在存档模式下运行的全节点。
存档节点本质上包含了整个区块链的快照,并持有从创世区块(第一个被开采的区块)开始的所有先前的网络状态。这使得存档节点非常适合快速查询历史数据,而不需要状态重建,这对于创建分析工具、DApps和其他需要快速访问历史的服务的开发者来说是理想的。
由于存档节点保留了整个链的状态,它们的大小也比全节点大得多。在撰写本文时,以太坊主网的规模约为10TB([etherscan.io](https://etherscan.io/chartsync/chainarchive))。
要启动一个新的存档节点,系统需要同步所有这些数据,然后才能开始在网络上运行。这导致了高额的启动和维护成本,鉴于此时需要几个月的时间来完成同步过程,而且为了跟上不断增长的磁盘大小需求,必须不断进行维护。

### 存档的主网状态大小(供参考)
请注意,这些数据一直在增长,这些数据在本文发表时是有效的。
– 以太坊主网:~12 TB
– Polygon主网:~16 TB
– BNB智能链:~7 TB
– Fantom主网:~4 TB
– Harmony主网:~20 TB
– Avalanche主网:~3 TB
请注意,BNB智能链使用Erigon客户端,与Geth相比,占用较小空间

这显示了所有这些链包含了多少数据,如果你想自己建立节点,你需要下载所有这些数据,并在能够运行节点之前对其进行验证。这对于一个存档节点来说可能需要几个月的时间。
## 在几分钟内部署一个节点
由于Chainstack等第三方节点的存在,你可以在几分钟内部署自己的节点。使用我们的快速同步技术[称为Bolt](https://chainstack.com/introducing-bolt-the-chainstack-technology-made-for-simple-node-synchronization/),Chainstack允许你在短短几分钟内部署一个全节点或存档节点,节省了数周或数月的工作和资源。
要获得一个节点:
1. [在Chainstack注册](https://console.chainstack.com/user/account/create)。
2. [部署一个全节点或存档节点](https://docs.chainstack.com/platform/join-a-public-network)。
## 获取过去状态的方法
现在很明显,要访问比最后128个块更早的数据,我们需要使用一个存档节点。
以下[Geth JSON-RPC方法](https://eth.wiki/json-rpc/API#the-default-block-parameter)包括一个参数,允许用户指定从哪个块检索数据:
– [eth_getBalance](https://eth.wiki/json-rpc/API#eth_getbalance)
– [eth_getCode](https://eth.wiki/json-rpc/API#eth_getcode)
– [eth_getTransactionCount](https://eth.wiki/json-rpc/API#eth_gettransactioncount)
– [eth_getStorageAt](https://eth.wiki/json-rpc/API#eth_getstorageat)
– [eth_call](https://eth.wiki/json-rpc/API#eth_call)
让我们依次看看这些方法,并尝试调用一下。
同样,如果你需要快速访问一个存档节点,可以在[Chainstack获取一个](https://console.chainstack.com/user/account/create)。
### eth_getBalance
检索一个特定时间点(区块)的地址余额,详情请见以太坊 Wiki:[eth_getBalance](https://eth.wiki/json-rpc/API#eth_getbalance)
#### **Web3.py**
使用web3.py从区块编号1的状态中检索地址余额。
在一个全节点上运行这段代码将返回一个错误,因为我们获取[区块高度1](https://etherscan.io/block/1)时一个地址的余额:
“`python
from web3 import Web3
node_url = “CHAINSTACK_ARCHIVE_NODE_URL”
web3 = Web3(Web3.HTTPProvider(node_url))
balance = web3.eth.get_balance(“0x9D00f1630b5B18a74231477B7d7244f47138ab47”, 1)
print(web3.fromWei(balance, “ether”))
“`
我们仍然可以在一个全节点上运行`eth_getBalance`,但是不能回溯到超过128个块。
#### **Web3.js**
使用web3.js获取一个地址余额。在下面是获取[区块块号14641000](https://etherscan.io/block/14641000)的地址余额:
“`javascript
var Web3 = require(‘web3’)
var node_URL = ‘CHAINSTACK_ARCHIVE_NODE_URL’
var web3 = new Web3(node_URL)
web3.eth.getBalance(‘0x9D00f1630b5B18a74231477B7d7244f47138ab47’, 14641000, (err, balance) => {
console.log(web3.utils.fromWei(balance, ‘ether’))
})
“`
`fromWei`方法用于将从节点(Wei)收到的数字转换成对我们可读的单位表示(ether)的数字。
#### **cURL**
使用cURL检索一个地址余额。在下面查询的是[区块编号14641000](https://etherscan.io/block/14641000)的状态。
注意,区块高度和返回值都是十六进制:
“`bash
curl CHAINSTACK_ARCHIVE_NODE_URL \
-X POST \
-H “Content-Type: application/json” \
–data ‘{“method”:”eth_getBalance”,”params”:[“0x9D00f1630b5B18a74231477B7d7244f47138ab47”, “0xDF6768″],”id”:1,”jsonrpc”:”2.0″}’
“`
### **eth_getCode**
返回一个智能合约的编译字节码,详情请见以太坊 Wiki[eth_getCode](https://eth.wiki/json-rpc/API#eth_getcode)。
下面的例子将得到[Uniswap token](https://etherscan.io/address/0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984#code)在部署时第一个区块的状态下的字节码,[区块高度10861674](https://etherscan.io/block/10861674)。
#### Web3.py
“`python
from web3 import Web3
node_url = “CHAINSTACK_ARCHIVE_NODE_URL”
web3 = Web3(Web3.HTTPProvider(node_url))
code = web3.eth.get_code(“0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984”, 10861674)
print(code)
“`
#### Web3.js
“`javascript
var Web3 = require(‘web3’)
var node_URL = ‘CHAINSTACK_ARCHIVE_NODE_URL’
var web3 = new Web3(node_URL)
web3.eth.getCode(‘0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984’, 10861674, (err, byte) => {
console.log(byte)
})
“`
#### **cURL**
注意,区块高度是十六进制:
“`css
curl CHAINSTACK_ARCHIVE_NODE_URL \
-X POST \
-H “Content-Type: application/json” \
–data ‘{“method”:”eth_getCode”,”params”:[“0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984”, “0xA5BC6A”],”id”:1,”jsonrpc”:”2.0″}’
“`
`getCode`RPC方法可以用来验证合约是否被正确部署或[销毁](https://docs.soliditylang.org/en/v0.4.21/introduction-to-smart-contracts.html#self-destruct)。
### eth_getTransactionCount
返回在特定区块下从一个地址发送的交易数量。详情请见以太坊 Wiki [eth_getTransactionCount](https://eth.wiki/json-rpc/API#eth_gettransactioncount)。
下面的例子将获取一个地址在[区块高度14674300](https://etherscan.io/block/14674300)状态下的交易数量(nonce)。
#### Web3.py
“`python
from web3 import Web3
node_url = “CHAINSTACK_ARCHIVE_NODE_URL”
web3 = Web3(Web3.HTTPProvider(node_url))
tx_count = web3.eth.get_transaction_count(“0x9D00f1630b5B18a74231477B7d7244f47138ab47”, 14674300)
print(tx_count)
“`
#### Web3.js
“`javascript
var Web3 = require(‘web3’);
var node_URL = ‘CHAINSTACK_ARCHIVE_NODE_URL’;
var web3 = new Web3(node_URL);
web3.eth.getTransactionCount(‘0x9D00f1630b5B18a74231477B7d7244f47138ab47’, 14674300, (err, count) => {
console.log(count)
})
“`
#### cURL
注意,区块编号和返回值都是十六进制:
“`bash
curl CHAINSTACK_ARCHIVE_NODE_URL \
-X POST \
-H “Content-Type: application/json” \
–data ‘{“method”:”eth_getTransactionCount”,”params”:[“0x9D00f1630b5B18a74231477B7d7244f47138ab47”, “0xDFE97C”],”id”:1,”jsonrpc”:”2.0″}’
“`
`getTransactionCount` RPC方法用于获取一个地址的nonce,nonce是一个整数值,代表该账户发送了多少交易。同样用来避免重复交易。
### eth_getStorageAt
返回一个给定地址的存储位置的值,详情请见以太坊 Wiki [eth_getStorageAt](https://eth.wiki/json-rpc/API#eth_getstorageat)。
下面的例子将返回[简单存储合约](https://etherscan.io/address/0x954De93D9f1Cd1e2e3AE5964F614CDcc821Fac64#readContract)的存储值。
最后一次值变化是在[区块高度 7500943](https://etherscan.io/tx/0xc6d494c08ee2a0144e6241f86e6128dcc6888116a863a865074af8b25841a608#eventlog),所以你可以把它作为一个参考点,以及检索不同区块高度的存储值。
#### Web3.py
“`python
from web3 import Web3
node_url = “CHAINSTACK_ARCHIVE_NODE_URL”
web3 = Web3(Web3.HTTPProvider(node_url))
storage = web3.eth.get_storage_at(“0x954De93D9f1Cd1e2e3AE5964F614CDcc821Fac64”, 0, 7500943)
print(storage.decode(“ASCII”))
“`
#### Web3.js
“`javascript
var Web3 = require(‘web3’);
var node_URL = ‘CHAINSTACK_ARCHIVE_NODE_URL’;
var web3 = new Web3(node_URL);
web3.eth.getStorageAt(‘0x954De93D9f1Cd1e2e3AE5964F614CDcc821Fac64’, 0, 7500943).then(result => {
console.log(web3.utils.hexToAscii(result));
});
“`
#### cURL
注意,区块编号和返回值都是十六进制:
“`bash
curl CHAINSTACK_ARCHIVE_NODE_URL \
-X POST \
-H “Content-Type: application/json” \
–data ‘{“method”:”eth_getStorageAt”,”params”:[“0x954De93D9f1Cd1e2e3AE5964F614CDcc821Fac64”, “0”, “0x72748F”],”id”:1,”jsonrpc”:”2.0″}’
“`
### eth_call
在区块链上进行只读调用,不改变任何状态。 详情请见以太坊 Wiki [eth_call](https://eth.wiki/json-rpc/API#eth_call)。
下面的例子为[区块高度 14000000](https://etherscan.io/block/14000000)的[Chainlink token](https://etherscan.io/address/0x514910771AF9Ca656af840dff83E8264EcF986CA)地址调用[Chainlink VRF coordinator](https://etherscan.io/address/0x271682DEB8C4E0901D1a1550aD2e64D568E69909)的`balanceOf`函数:
#### **Web3.py**
“`swift
import json
from web3 import Web3
node_url = “CHAINSTACK_ARCHIVE_NODE_URL”
web3 = Web3(Web3.HTTPProvider(node_url))
abi=json.loads(‘[{“constant”:true,”inputs”:[],”name”:”name”,”outputs”:[{“name”:””,”type”:”string”}],”payable”:false,”stateMutability”:”view”,”type”:”function”},{“constant”:false,”inputs”:[{“name”:”_spender”,”type”:”address”},{“name”:”_value”,”type”:”uint256″}],”name”:”approve”,”outputs”:[{“name”:””,”type”:”bool”}],”payable”:false,”stateMutability”:”nonpayable”,”type”:”function”},{“constant”:true,”inputs”:[],”name”:”totalSupply”,”outputs”:[{“name”:””,”type”:”uint256″}],”payable”:false,”stateMutability”:”view”,”type”:”function”},{“constant”:false,”inputs”:[{“name”:”_from”,”type”:”address”},{“name”:”_to”,”type”:”address”},{“name”:”_value”,”type”:”uint256″}],”name”:”transferFrom”,”outputs”:[{“name”:””,”type”:”bool”}],”payable”:false,”stateMutability”:”nonpayable”,”type”:”function”},{“constant”:true,”inputs”:[],”name”:”decimals”,”outputs”:[{“name”:””,”type”:”uint8″}],”payable”:false,”stateMutability”:”view”,”type”:”function”},{“constant”:false,”inputs”:[{“name”:”_to”,”type”:”address”},{“name”:”_value”,”type”:”uint256″},{“name”:”_data”,”type”:”bytes”}],”name”:”transferAndCall”,”outputs”:[{“name”:”success”,”type”:”bool”}],”payable”:false,”stateMutability”:”nonpayable”,”type”:”function”},{“constant”:false,”inputs”:[{“name”:”_spender”,”type”:”address”},{“name”:”_subtractedValue”,”type”:”uint256″}],”name”:”decreaseApproval”,”outputs”:[{“name”:”success”,”type”:”bool”}],”payable”:false,”stateMutability”:”nonpayable”,”type”:”function”},{“constant”:true,”inputs”:[{“name”:”_owner”,”type”:”address”}],”name”:”balanceOf”,”outputs”:[{“name”:”balance”,”type”:”uint256″}],”payable”:false,”stateMutability”:”view”,”type”:”function”},{“constant”:true,”inputs”:[],”name”:”symbol”,”outputs”:[{“name”:””,”type”:”string”}],”payable”:false,”stateMutability”:”view”,”type”:”function”},{“constant”:false,”inputs”:[{“name”:”_to”,”type”:”address”},{“name”:”_value”,”type”:”uint256″}],”name”:”transfer”,”outputs”:[{“name”:”success”,”type”:”bool”}],”payable”:false,”stateMutability”:”nonpayable”,”type”:”function”},{“constant”:false,”inputs”:[{“name”:”_spender”,”type”:”address”},{“name”:”_addedValue”,”type”:”uint256″}],”name”:”increaseApproval”,”outputs”:[{“name”:”success”,”type”:”bool”}],”payable”:false,”stateMutability”:”nonpayable”,”type”:”function”},{“constant”:true,”inputs”:[{“name”:”_owner”,”type”:”address”},{“name”:”_spender”,”type”:”address”}],”name”:”allowance”,”outputs”:[{“name”:”remaining”,”type”:”uint256″}],”payable”:false,”stateMutability”:”view”,”type”:”function”},{“inputs”:[],”payable”:false,”stateMutability”:”nonpayable”,”type”:”constructor”},{“anonymous”:false,”inputs”:[{“indexed”:true,”name”:”from”,”type”:”address”},{“indexed”:true,”name”:”to”,”type”:”address”},{“indexed”:false,”name”:”value”,”type”:”uint256″},{“indexed”:false,”name”:”data”,”type”:”bytes”}],”name”:”Transfer”,”type”:”event”},{“anonymous”:false,”inputs”:[{“indexed”:true,”name”:”owner”,”type”:”address”},{“indexed”:true,”name”:”spender”,”type”:”address”},{“indexed”:false,”name”:”value”,”type”:”uint256″}],”name”:”Approval”,”type”:”event”}]’)
address = “0x514910771AF9Ca656af840dff83E8264EcF986CA”
contract = web3.eth.contract(address=address, abi=abi)
balance = contract.functions.balanceOf(‘0x271682DEB8C4E0901D1a1550aD2e64D568E69909’).call(block_identifier=14000000)
print(web3.fromWei(balance, ‘ether’))
“`
#### **Web3.js**
“`javascript
const Web3 = require(‘web3’);
const web3 = new Web3(new Web3.providers.HttpProvider(“CHAINSTACK_ARCHIVE_NODE_URL”));
web3.eth.defaultBlock = 14000000;
web3.eth.call({
to: “0x514910771AF9Ca656af840dff83E8264EcF986CA”,
data: “0x70a08231000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909”
})
.then(result => {
console.log(web3.utils.fromWei(result));
});
“`
#### **cURL**
注意,区块编号和返回值都是十六进制:
“`bash
curl CHAINSTACK_ARCHIVE_NODE_URL \
-X POST \
-H “Content-Type: application/json” \
–data ‘{“method”:”eth_call”,”params”:[{“from”:null,”to”:”0x514910771AF9Ca656af840dff83E8264EcF986CA”,”data”:”0x70a08231000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909″}, “0xD59F80″],”id”:1,”jsonrpc”:”2.0″}’
“`
## 结论
存档节点持有区块链的 “历史”,并拥有从创世区块开始网络中的每个先前状态的记录。这意味着可以快速访问历史数据,使用Chainstack,你可以轻而易举地建立一个存档节点!
存档节点是一个很好的开发工具,特别是当你需要查询过去的数据时,例如,如果你正在使用Hardhat、Ganache和其他开发框架来分叉主网,用于运行本地模拟区块链进行测试和开发,或者如果你在创建一个区块链资源管理器、区块链分析工具、用The Graph等协议进行区块链索引等等,因为你可以即时访问全链。
如果你正在DApp,通常最新128个区块内的数据就足够了,这是仅需要一个全节点。
——
本翻译由 [Duet Protocol](https://duet.finance/?utm_souce=learnblockchain) 赞助支持。
- 原文:https://chainstack.com/evm-nodes-a-dive-into-the-full-vs-archive-mode/
- 译文出自:区块链开发网翻译计划
- 译者:翻译小组
- 校对:Tiny 熊
- 本文永久链接:learnblockchain.cn/article…
简介
基于以太坊虚拟机(EVM)的网络通常可以运行两种类型的节点:一个全节点和一个存档节点。
许多流行网络基于EVM:包括以太坊 、Polygon 、BNB Smart Chain、C-Chain of Avalanche 、Fantom、Harmony等。
全节点和存档节点两者都存储完整的区块链数据,可用于重放网络状态,但区别在于,存档节点另外将每个区块的网络状态存储在一个存档中,可供查询。
这就是简短的解释。
在这篇文章中,我们将深入探讨全节点和存档节点的一些细节、区别和操作实例。
Geth和Erigon
首先,简单介绍一下节点客户端:
Go 以太坊(Geth)是迄今为止最流行的基于EVM的网络的客户端软件,可能在整个区块链领域都是如此。
对于以太坊主网,你可以在ethernodes crawler data查看节点客户端分布。
Chainstack支持使用Geth客户端或Erigon客户端(以前是Turbo-Geth)来运行以太坊节点–后者是另一个Go实现客户端,专注于效率,是第二流行的客户端。
在这篇文章中,我们将重点介绍Geth和Erigon在全节点和存档节点模式下的实现。
全节点和存档节点
让我们深入了解一下细节:
全节点
- 存储完整的区块链数据。
- 验证所有区块和状态。
- 所有的状态都可以从一个完整的节点重新生成。
一个完整的EVM节点保持区块链的当前状态,并处理读取调用(view)和状态改变的调用(交易)。一个完整的节点会修剪区块链数据,以节省磁盘空间并减少同步时间,但在必要时存储足够的数据来重新计算链上的事件,使得它的运行效率更高,但它也限制请求特定数量的区块的数据(通常为128个区块)。
例如,在以太坊主网上,产生一个新区块的平均时间约为13秒,你只能检索过去28-29分钟的链状态。虽然在理论上,你可以使用一个完整的节点来重新计算所有的中间状态,但这将需要特别长的时间,而且将是非常密集的资源,你的节点可能会耗尽内存而停止。
默认的返回状态和 Missing trie node
的错误
根据所访问的链和所使用的客户端,被限制能访问多少个可用的区块状态有所不同:
- 以太坊:128个区块
- Polygon: 128个区块
- BNB智能链: 128个区块
- Avalanche C-Chain:32个区块
- Fantom: Go Opera客户端不修剪信息,所以在全节点和存档节点之间没有区别。
- Harmony: 128个区块
如果你试图查询一个不能从全节点访问的区块,你会收到一个missing trie node的错误。
一般来说,收到missing trie node的错误意味着你需要一个存档节点。
存档节点
- 存储所有保存在全节点中的东西,并建立一个历史状态的档案。
- 他们是配置为在存档模式下运行的全节点。
存档节点本质上包含了整个区块链的快照,并持有从创世区块(第一个被开采的区块)开始的所有先前的网络状态。这使得存档节点非常适合快速查询历史数据,而不需要状态重建,这对于创建分析工具、DApps和其他需要快速访问历史的服务的开发者来说是理想的。
由于存档节点保留了整个链的状态,它们的大小也比全节点大得多。在撰写本文时,以太坊主网的规模约为10TB(etherscan.io)。
要启动一个新的存档节点,系统需要同步所有这些数据,然后才能开始在网络上运行。这导致了高额的启动和维护成本,鉴于此时需要几个月的时间来完成同步过程,而且为了跟上不断增长的磁盘大小需求,必须不断进行维护。
存档的主网状态大小(供参考)
请注意,这些数据一直在增长,这些数据在本文发表时是有效的。
- 以太坊主网:~12 TB
- Polygon主网:~16 TB
- BNB智能链:~7 TB
- Fantom主网:~4 TB
- Harmony主网:~20 TB
- Avalanche主网:~3 TB
请注意,BNB智能链使用Erigon客户端,与Geth相比,占用较小空间
这显示了所有这些链包含了多少数据,如果你想自己建立节点,你需要下载所有这些数据,并在能够运行节点之前对其进行验证。这对于一个存档节点来说可能需要几个月的时间。
在几分钟内部署一个节点
由于Chainstack等第三方节点的存在,你可以在几分钟内部署自己的节点。使用我们的快速同步技术称为Bolt,Chainstack允许你在短短几分钟内部署一个全节点或存档节点,节省了数周或数月的工作和资源。
要获得一个节点:
- 在Chainstack注册。
- 部署一个全节点或存档节点。
获取过去状态的方法
现在很明显,要访问比最后128个块更早的数据,我们需要使用一个存档节点。
以下Geth JSON-RPC方法包括一个参数,允许用户指定从哪个块检索数据:
- eth_getBalance
- eth_getCode
- eth_getTransactionCount
- eth_getStorageAt
- eth_call
让我们依次看看这些方法,并尝试调用一下。
同样,如果你需要快速访问一个存档节点,可以在Chainstack获取一个。
eth_getBalance
检索一个特定时间点(区块)的地址余额,详情请见以太坊 Wiki:eth_getBalance
Web3.py
使用web3.py从区块编号1的状态中检索地址余额。
在一个全节点上运行这段代码将返回一个错误,因为我们获取区块高度1时一个地址的余额:
from web3 import Web3
node_url = "CHAINSTACK_ARCHIVE_NODE_URL"
web3 = Web3(Web3.HTTPProvider(node_url))
balance = web3.eth.get_balance("0x9D00f1630b5B18a74231477B7d7244f47138ab47", 1)
print(web3.fromWei(balance, "ether"))
我们仍然可以在一个全节点上运行eth_getBalance
,但是不能回溯到超过128个块。
Web3.js
使用web3.js获取一个地址余额。在下面是获取区块块号14641000的地址余额:
var Web3 = require('web3')
var node_URL = 'CHAINSTACK_ARCHIVE_NODE_URL'
var web3 = new Web3(node_URL)
web3.eth.getBalance('0x9D00f1630b5B18a74231477B7d7244f47138ab47', 14641000, (err, balance) => {
console.log(web3.utils.fromWei(balance, 'ether'))
})
fromWei
方法用于将从节点(Wei)收到的数字转换成对我们可读的单位表示(ether)的数字。
cURL
使用cURL检索一个地址余额。在下面查询的是区块编号14641000的状态。
注意,区块高度和返回值都是十六进制:
curl CHAINSTACK_ARCHIVE_NODE_URL \
-X POST \
-H "Content-Type: application/json" \
--data '{"method":"eth_getBalance","params":["0x9D00f1630b5B18a74231477B7d7244f47138ab47", "0xDF6768"],"id":1,"jsonrpc":"2.0"}'
eth_getCode
返回一个智能合约的编译字节码,详情请见以太坊 Wikieth_getCode。
下面的例子将得到Uniswap token在部署时第一个区块的状态下的字节码,区块高度10861674。
Web3.py
from web3 import Web3
node_url = "CHAINSTACK_ARCHIVE_NODE_URL"
web3 = Web3(Web3.HTTPProvider(node_url))
code = web3.eth.get_code("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984", 10861674)
print(code)
Web3.js
var Web3 = require('web3')
var node_URL = 'CHAINSTACK_ARCHIVE_NODE_URL'
var web3 = new Web3(node_URL)
web3.eth.getCode('0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', 10861674, (err, byte) => {
console.log(byte)
})
cURL
注意,区块高度是十六进制:
curl CHAINSTACK_ARCHIVE_NODE_URL \
-X POST \
-H "Content-Type: application/json" \
--data '{"method":"eth_getCode","params":["0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984", "0xA5BC6A"],"id":1,"jsonrpc":"2.0"}'
getCode
RPC方法可以用来验证合约是否被正确部署或销毁。
eth_getTransactionCount
返回在特定区块下从一个地址发送的交易数量。详情请见以太坊 Wiki eth_getTransactionCount。
下面的例子将获取一个地址在区块高度14674300状态下的交易数量(nonce)。
Web3.py
from web3 import Web3
node_url = "CHAINSTACK_ARCHIVE_NODE_URL"
web3 = Web3(Web3.HTTPProvider(node_url))
tx_count = web3.eth.get_transaction_count("0x9D00f1630b5B18a74231477B7d7244f47138ab47", 14674300)
print(tx_count)
Web3.js
var Web3 = require('web3');
var node_URL = 'CHAINSTACK_ARCHIVE_NODE_URL';
var web3 = new Web3(node_URL);
web3.eth.getTransactionCount('0x9D00f1630b5B18a74231477B7d7244f47138ab47', 14674300, (err, count) => {
console.log(count)
})
cURL
注意,区块编号和返回值都是十六进制:
curl CHAINSTACK_ARCHIVE_NODE_URL \
-X POST \
-H "Content-Type: application/json" \
--data '{"method":"eth_getTransactionCount","params":["0x9D00f1630b5B18a74231477B7d7244f47138ab47", "0xDFE97C"],"id":1,"jsonrpc":"2.0"}'
getTransactionCount
RPC方法用于获取一个地址的nonce,nonce是一个整数值,代表该账户发送了多少交易。同样用来避免重复交易。
eth_getStorageAt
返回一个给定地址的存储位置的值,详情请见以太坊 Wiki eth_getStorageAt。
下面的例子将返回简单存储合约的存储值。
最后一次值变化是在区块高度 7500943,所以你可以把它作为一个参考点,以及检索不同区块高度的存储值。
Web3.py
from web3 import Web3
node_url = "CHAINSTACK_ARCHIVE_NODE_URL"
web3 = Web3(Web3.HTTPProvider(node_url))
storage = web3.eth.get_storage_at("0x954De93D9f1Cd1e2e3AE5964F614CDcc821Fac64", 0, 7500943)
print(storage.decode("ASCII"))
Web3.js
var Web3 = require('web3');
var node_URL = 'CHAINSTACK_ARCHIVE_NODE_URL';
var web3 = new Web3(node_URL);
web3.eth.getStorageAt('0x954De93D9f1Cd1e2e3AE5964F614CDcc821Fac64', 0, 7500943).then(result => {
console.log(web3.utils.hexToAscii(result));
});
cURL
注意,区块编号和返回值都是十六进制:
curl CHAINSTACK_ARCHIVE_NODE_URL \
-X POST \
-H "Content-Type: application/json" \
--data '{"method":"eth_getStorageAt","params":["0x954De93D9f1Cd1e2e3AE5964F614CDcc821Fac64", "0", "0x72748F"],"id":1,"jsonrpc":"2.0"}'
eth_call
在区块链上进行只读调用,不改变任何状态。 详情请见以太坊 Wiki eth_call。
下面的例子为区块高度 14000000的Chainlink token地址调用Chainlink VRF coordinator的balanceOf
函数:
Web3.py
import json
from web3 import Web3
node_url = "CHAINSTACK_ARCHIVE_NODE_URL"
web3 = Web3(Web3.HTTPProvider(node_url))
abi=json.loads('[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"transferAndCall","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"data","type":"bytes"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}]')
address = "0x514910771AF9Ca656af840dff83E8264EcF986CA"
contract = web3.eth.contract(address=address, abi=abi)
balance = contract.functions.balanceOf('0x271682DEB8C4E0901D1a1550aD2e64D568E69909').call(block_identifier=14000000)
print(web3.fromWei(balance, 'ether'))
Web3.js
const Web3 = require('web3');
const web3 = new Web3(new Web3.providers.HttpProvider("CHAINSTACK_ARCHIVE_NODE_URL"));
web3.eth.defaultBlock = 14000000;
web3.eth.call({
to: "0x514910771AF9Ca656af840dff83E8264EcF986CA",
data: "0x70a08231000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909"
})
.then(result => {
console.log(web3.utils.fromWei(result));
});
cURL
注意,区块编号和返回值都是十六进制:
curl CHAINSTACK_ARCHIVE_NODE_URL \
-X POST \
-H "Content-Type: application/json" \
--data '{"method":"eth_call","params":[{"from":null,"to":"0x514910771AF9Ca656af840dff83E8264EcF986CA","data":"0x70a08231000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909"}, "0xD59F80"],"id":1,"jsonrpc":"2.0"}'
结论
存档节点持有区块链的 “历史”,并拥有从创世区块开始网络中的每个先前状态的记录。这意味着可以快速访问历史数据,使用Chainstack,你可以轻而易举地建立一个存档节点!
存档节点是一个很好的开发工具,特别是当你需要查询过去的数据时,例如,如果你正在使用Hardhat、Ganache和其他开发框架来分叉主网,用于运行本地模拟区块链进行测试和开发,或者如果你在创建一个区块链资源管理器、区块链分析工具、用The Graph等协议进行区块链索引等等,因为你可以即时访问全链。
如果你正在DApp,通常最新128个区块内的数据就足够了,这是仅需要一个全节点。
本翻译由 Duet Protocol 赞助支持。
本文参与区块链开发网写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
- 发表于 2022-07-28 16:00
- 阅读 ( 570 )
- 学分 ( 72 )
- 分类:以太坊