基于以太坊的区块链首次同步

通常,在同步以太坊区块链时,你的客户端将下载并验证自创世区块以来的每个区块和每个交易。

虽然可以通过这种方式完整同步区块链,但同步会花费很长时间并且对计算资源要求较高(RAM更多,存储速度更快)。

许多基于以太坊的区块链在2016年底遭受了拒绝服务(DoS)攻击。受此攻击影响的区块链在进行完全同步时倾向于缓慢同步。

例如,在以太坊中,新客户端在到达区块2,283,397之前会进展迅速。该块在2016年9月18日开采,标志着DoS攻击的开始。从这个区块到2,700,031区块(2016年11月26日),交易验证变得非常缓慢,内存密集并且I/O密集。这导致每块的验证时间超过1分钟。以太坊使用硬分叉实施了一系列升级,以解决在拒绝服务中被利用的底层漏洞。这些升级还通过删除由垃圾邮件交易创建的大约2000万个空帐户来清理区块链。<<[1]>>

如果你正在使用完整验证进行同步,则客户端会放慢速度并可能需要几天或更长时间才能验证受此DoS攻击影响的任何块。

大多数以太坊客户端包括一个选项,可以执行“快速”同步,跳过交易的完整验证,同步到区块链的顶端后,再恢复完整验证。

对于Geth,启用快速同步的选项通常称为 —fast。你可能需要参考你选择的以太坊链的具体说明。

对于Parity,较旧版本(<1.6),该选项为 —warp,较新版本(>=1.6)上默认启用(无需设置配置选项)。

Note

Geth和Parity只能在空的区块数据库启动时进行快速同步。如果你已经开始没有“快速”模式的同步,则Geth和Parity无法切换。删除区块链数据目录并从头开始“快速”同步比继续完整验证同步更快。删除区块链数据时请小心不要删除任何钱包!

JSON-RPC接口

以太坊客户端提供应用程序编程接口(API)和一组远程过程调用(RPC)命令,这些命令被编码为JavaScript对象表示法(JSON)。这被称为_JSON-RPC API_。本质上,JSON-RPC API是一个接口,允许我们将使用以太坊客户端的程序作为_gateway_编写到以太坊网络和区块链中。

通常,RPC接口作为端口+8545+上的HTTP服务提供。出于安全原因,默认情况下,它仅受限于从本地主机(你自己的计算机的IP地址为+127.0.0.1+)接受连接。

要访问JSON-RPC API,可以使用专门的库,用你选择的编程语言编写,它提供与每个可用的RPC命令相对应的“桩(stub)”函数调用。或者,你可以手动构建HTTP请求并发送/接收JSON编码的请求。你甚至可以使用通用命令行HTTP客户端(如 curl )来调用RPC接口。让我们尝试一下(确保你已经配置并运行了Geth):

Using curl to call the web3_clientVersion function over JSON-RPC

  1. $ curl -X POST -H "Content-Type: application/json" --data \
  2. '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":1}' \
  3. http://localhost:8545
  4. {"jsonrpc":"2.0","id":1,
  5. "result":"Geth/v1.8.0-unstable-02aeb3d7/linux-amd64/go1.8.3"}

在这个例子中,我们使用 curl 建立一个HTTP连接来访问 http://localhost:8545。我们已经运行了 geth,它将JSON-RPC API作为端口8545上的HTTP服务提供。我们指示 curl 使用HTTP POST 命令并将内容标识为 Content-Type: application/json。最后,我们传递一个JSON编码的请求作为我们HTTP请求的+data+部分。我们的大多数命令行只是设置 curl 来正确地建立HTTP连接。有趣的部分是我们发布的实际的JSON-RPC命令:

  1. {"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":4192}

JSON-RPC请求根据JSON-RPC 2.0规范格式化,你可以在这里看到: http://www.jsonrpc.org/specification

每个请求包含4个元素:

jsonrpc

JSON-RPC协议的版本。这_必须_是“2.0”。

method

要调用的方法的名称。

params

一个结构化值,用于保存在调用方法期间要使用的参数值。该元素可以省略。

id

由客户端建立的标识符,必须包含字符串,数字或NULL值(如果包含)。如果包含,服务器必须在Response对象中使用相同的值进行回复。该元素用于关联两个对象之间的上下文。

Tip

id 参数主要用于在单个JSON-RPC调用中进行多个请求的情况,这种做法称为批处理。批处理用于避免每个请求的新HTTP和TCP连接的开销。例如,在以太坊环境中,如果我们想要在一个HTTP连接中检索数千个交易,我们将使用批处理。批处理时,为每个请求设置不同的 id,然后将其与来自JSON-RPC服务器的每个响应中的+id+进行匹配。实现这个最简单的方法是维护一个计数器并为每个请求增加值。

The response we receive is:

  1. {"jsonrpc":"2.0","id":4192,
  2. "result":"Geth/v1.8.0-unstable-02aeb3d7/linux-amd64/go1.8.3"}

这告诉我们JSON-RPC API由Geth客户端版本1.8.0提供服务。

让我们尝试一些更有趣的事情。在下一个例子中,我们要求JSON-RPC API获取当前的gas价格,以wei为单位:

  1. $ curl -X POST -H "Content-Type: application/json" --data \
  2. '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":4213}' \
  3. http://localhost:8545
  4. {"jsonrpc":"2.0","id":4213,"result":"0x430e23400"}

响应 0x430e23400 告诉我们,当前的gas价格是1.8wei(gigawei或十亿wei)。

https://github.com/ethereum/wiki/wiki/JSON-RPC

Parity的Geth兼容模式

有一个特殊的“Geth兼容模式”,它提供了一个与+geth+相同的JSON-RPC API。要在Geth兼容模式下运行奇偶校验,请使用+—geth+开关:

  1. $ parity --geth