以太坊源码解析(六)JSON-RPC API
JSON-RPC服务器
Geth支持所有标准的web3 JSON-RPC API。您可以在Ethereum Wiki JSON-RPC页面上找到这些API的文档。
JSON-RPC在多种传输方式上提供。Geth支持基于HTTP,WebSocket和Unix域套接字的JSON-RPC。必须通过命令行标志启用传输。
以太坊JSON-RPC API使用命名空间系统。RPC方法根据其用途分为几类。所有方法名称均由名称空间,下划线和名称空间内的实际方法名称组成。例如,该eth_call
方法位于eth
名称空间中。
可以基于每个命名空间启用对RPC方法的访问。在边栏中查找各个名称空间的文档。
HTTP服务器
要启用HTTP服务器,请使用--rpc
标志。
1 | geth --rpc |
默认情况下,geth接受来自回送接口(127.0.0.1)的连接。默认监听端口为8545。您可以使用--rpcport
和--rpcaddr
标志来自定义地址和端口 。
1 | geth --rpc --rpcport 3334 |
必须将JSON-RPC方法名称空间列入白名单,才能通过HTTP服务器使用。-32602
如果调用未列入白名单的名称空间,则会生成带有错误代码的RPC错误。默认白名单允许访问“ eth”和“ shh”名称空间。要启用对其他API(例如帐户管理(“个人”)和调试(“调试”))的访问,必须通过该--rpcapi
标志对其进行配置。我们不建议您通过HTTP启用此类API,因为对这些方法的访问会增加攻击面。
1 | geth --rpc --rpcapi personal,eth,net,web3b |
由于可以从任何本地应用程序访问HTTP服务器,因此服务器中内置了附加保护功能,以防止从网页滥用API。如果要允许从网页访问API,则必须将服务器配置为接受带有--rpccorsdomain
标志的跨域请求。
示例:如果您想将Remix与geth 一起使用,请允许来自remix域的请求。
1 | geth --rpc --rpccorsdomain https://remix.ethereum.org |
使用--rpccorsdomain '*'
,以便从任何来源获得。
WebSocket服务器
WebSocket终结点的配置类似于HTTP传输。要启用WebSocket访问,请使用--ws
标志。默认的WebSocket端口是8546。--wsaddr
,--wsport
和--wsapi
标志可用于自定义WebSocket服务器的设置。
1 | geth --ws --wsport 3334 --wsapi eth,net,web3 |
跨域请求保护也适用于WebSocket服务器。使用该 --wsorigins
标志允许从网页访问服务器:
1 | geth --ws --wsorigins http://myapp.example.com |
与一样--rpccorsdomain
,使用--wsorigins '*'
可以从任何来源访问。
IPC服务器
UNIX域套接字上还提供了JSON-RPC API。该服务器默认情况下处于启用状态,并且可以访问所有JSON-RPC名称空间。
默认情况下,侦听套接字位于数据目录中。在Linux和macOS上,geth套接字的默认位置是
1 | ~/.ethereum/geth.ipc |
在Windows上,通过命名管道提供IPC。geth管道的默认位置是:
1 | \\.\pipe\geth.ipc |
您可以使用该--ipcpath
标志配置套接字的位置。可以使用该--ipcdisable
标志禁用IPC 。
实时事件
Geth v1.4和更高版本支持使用JSON-RPC通知进行发布/订阅。这使客户端可以等待事件而不是轮询事件。
它通过订阅特定事件来工作。该节点将返回订阅ID。对于与订阅匹配的每个事件,带有相关数据的通知将与订阅ID一起发送。
例:
1 | // create subscription |
注意事项
- 通知是针对当前事件而不是针对过去事件发送的。如果您的用例要求您不要错过任何通知,那么订阅可能不是最佳选择。
- 订阅需要全双工连接。Geth以WebSocket和IPC的形式提供此类连接(默认情况下启用)。
- 订阅耦合到连接。如果连接已关闭,则将删除通过该连接创建的所有订阅。
- 通知存储在内部缓冲区中,并从该缓冲区发送到客户端。如果客户端无法跟上,并且缓冲的通知数达到限制(当前为10k),则连接将关闭。请记住,订阅某些事件可能会导致大量通知,例如,在节点开始同步时侦听所有日志/块。
创建订阅
订阅是使用常规RPC调用创建的,其中RPC eth_subscribe
作为方法,订阅名称为第一个参数。如果成功,则返回订阅ID。
参量
- 订阅名称
- 可选参数
例
1 | >> {"id": 1, "method": "eth_subscribe", "params": ["newHeads", {"includeTransactions": true}]} |
取消订阅
使用常规的RPC调用取消订阅,该调用使用eth_unsubscribe
as方法并将订阅id作为第一个参数。它返回一个布尔值,指示是否成功取消了订阅。
参量
- 订阅编号
例
1 | >> {"id": 1, "method": "eth_unsubscribe", "params": ["0x9cef478923ff08bf67fde6c64013158d"]} |
支持的订阅
newHeads
每次将新标头附加到链(包括链重组)时,都会触发通知。用户可以使用Bloom筛选器确定该块是否包含对其感兴趣的日志。
如果进行链重组,则订阅将发出新链的所有新标头。因此,订阅可以在相同高度上发出多个标头。
例
1 | >> {"id": 1, "method": "eth_subscribe", "params": ["newHeads"]} |
日志
返回包含在新导入的块中并符合给定过滤条件的日志。
如果进行链重组,则将重新发送旧链上的先前发送的日志,并将removed
属性设置为true。来自结束于新链中的事务的日志被发出。因此,订阅可以多次发出同一事务的日志。
参量
1
object
具有以下(可选)字段
- address,一个地址或一个地址数组。仅返回从这些地址创建的日志(可选)
- topic,仅匹配指定主题的日志(可选)
例
1 | >> {"id": 1, "method": "eth_subscribe", "params": ["logs", {"address": "0x8320fe7702b96808f7bbc0d4a888ed1468216cfd", "topics": ["0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902"]}]} |
newPendingTransactions
返回添加到挂起状态并使用节点中可用密钥签名的所有事务的哈希。
当重新定义后,以前属于规范链的交易不属于新规范链的交易。
参量
没有
例
1 | >> {"id": 1, "method": "eth_subscribe", "params": ["newPendingTransactions"]} |
正在同步
指示节点何时开始或停止同步。结果可以是指示同步已开始(true),完成(false)的布尔值,也可以是具有各种进度指示器的对象。
参量
没有
例
1 | >> {"id": 1, "method": "eth_subscribe", "params": ["syncing"]} |
管理员命名空间
该admin
API使您可以访问几种非标准RPC方法,这将使您能够对Geth实例进行精细控制,包括但不限于网络对等方和RPC端点管理。
admin_addPeer
该addPeer
管理方法要求将新的远程节点添加到跟踪的静态节点列表中。该节点将一直尝试保持与这些节点的连接,如果远程连接断开,则每隔一段时间重新连接一次。
该方法接受一个参数,即enode
远程对等方的URL以开始跟踪,并返回一个BOOL
指示是否接受对等方进行跟踪或发生了一些错误。
客户 | 方法调用 |
---|---|
Go | admin.AddPeer(url string) (bool, error) |
Console | admin.addPeer(url) |
RPC | {"method": "admin_addPeer", "params": [url]} |
例
1 | > admin.addPeer("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303") |
admin_datadir
该datadir
行政财产,可以被询问运行Geth的节点当前用来存储所有数据库的绝对路径。
客户 | 方法调用 |
---|---|
Go | admin.Datadir() (string, error ) |
Console | admin.datadir |
RPC | {"method": "admin_datadir"} |
例
1 | > admin.datadir |
admin_nodeInfo
nodeInfo
可以在网络粒度上查询有关正在运行的Geth节点的所有已知信息的管理属性。这些包括关于节点本身作为的参与者一般信息ÐΞVp2p P2P覆盖协议由每个运行的应用程序的协议加入,以及专门的信息(例如eth
,les
,shh
,bzz
)。
客户 | 方法调用 |
---|---|
Go | admin.NodeInfo() (*p2p.NodeInfo, error ) |
Console | admin.nodeInfo |
RPC | {"method": "admin_nodeInfo"} |
例
1 | > admin.nodeInfo |
admin_peers
peers
可以查询联网属性下有关连接的远程节点的所有已知信息的管理属性。这些包括关于节点本身作为参与者一般信息ÐΞVp2p P2P覆盖协议由每个运行的应用程序的协议加入,以及专门的信息(例如eth
,les
,shh
,bzz
)。
客户 | 方法调用 |
---|---|
Go | admin.Peers() ([]*p2p.PeerInfo, error ) |
Console | admin.peers |
RPC | {"method": "admin_peers"} |
例
1 | > admin.peers |
admin_startRPC
该startRPC
管理方法启动基于HTTP的JSON RPC API Web服务器来处理客户端请求。所有参数都是可选的:
host
:用于打开监听器套接字的网络接口(默认为"localhost"
)port
:用于打开侦听器套接字的网络端口(默认为8545
)cors
:要使用的跨域资源共享标头(默认为""
)apis
:通过此接口提供的API模块(默认为"eth,net,web3"
)
该方法返回一个布尔标志,用于指定是否打开HTTP RPC侦听器。请注意,任何时候都只允许一个HTTP端点处于活动状态。
客户 | 方法调用 |
---|---|
Go | admin.StartRPC(host *string, port *rpc.HexNumber, cors *string, apis *string) (bool, error) |
Console | admin.startRPC(host, port, cors, apis) |
RPC | {"method": "admin_startRPC", "params": [host, port, cors, apis]} |
例
1 | > admin.startRPC("127.0.0.1", 8545) |
admin_startWS
该startWS
管理方法启动基于WebSocket的JSON RPC API Web服务器来处理客户端请求。所有参数都是可选的:
host
:用于打开监听器套接字的网络接口(默认为"localhost"
)port
:用于打开侦听器套接字的网络端口(默认为8546
)cors
:要使用的跨域资源共享标头(默认为""
)apis
:通过此接口提供的API模块(默认为"eth,net,web3"
)
该方法返回一个布尔标志,指定是否打开WebSocket RPC侦听器。请注意,任何时候都只允许一个WebSocket端点处于活动状态。
客户 | 方法调用 |
---|---|
Go | admin.StartWS(host *string, port *rpc.HexNumber, cors *string, apis *string) (bool, error) |
Console | admin.startWS(host, port, cors, apis) |
RPC | {"method": "admin_startWS", "params": [host, port, cors, apis]} |
例
1 | > admin.startWS("127.0.0.1", 8546) |
admin_stopRPC
该stopRPC
管理方法将关闭当前打开的HTTP RPC端点。由于节点只能运行一个HTTP终结点,因此此方法不使用任何参数,无论终结点是否关闭,都返回一个布尔值。
客户 | 方法调用 |
---|---|
Go | admin.StopRPC() (bool, error ) |
Console | admin.stopRPC() |
RPC | {"method": "admin_stopRPC" |
例
1 | > admin.stopRPC() |
admin_stopWS
该stopWS
管理方法将关闭当前打开的WebSocket RPC端点。由于节点只能运行一个WebSocket端点,因此此方法不使用任何参数,无论端点是否关闭,都返回一个布尔值。
客户 | 方法调用 |
---|---|
Go | admin.StopWS() (bool, error ) |
Console | admin.stopWS() |
RPC | {"method": "admin_stopWS" |
例
1 | > admin.stopWS() |
集团命名空间
该clique
API提供对集团共识引擎状态的访问。您可以使用此API来管理签名者的投票并检查专用网络的运行状况。
clique_getSnapshot
检索给定块上所有集团状态的快照。
客户 | 方法调用 |
---|---|
Console | clique.getSnapshot(blockNumber) |
RPC | {"method": "clique_getSnapsnot", "params": [blockNumber]} |
例:
1 | > clique.getSnapshot(5463755) |
clique_getSnapshotAtHash
检索给定块上的状态快照。
客户 | 方法调用 |
---|---|
Console | clique.getSnapshotAtHash(blockHash) |
RPC | {"method": "clique_getSnapshotAtHash", "params": [blockHash]} |
clique_getSigners
检索指定块上的授权签署者列表。
客户 | 方法调用 |
---|---|
Console | clique.getSigners(blockNumber) |
RPC | {"method": "clique_getSigners", "params": [blockNumber]} |
clique_proposals
返回节点正在投票的当前投标。
客户 | 方法调用 |
---|---|
Console | clique.proposals() |
RPC | {"method": "clique_proposals", "params": []} |
clique_propose
添加签名者将尝试推送的新授权提议。如果 auth
参数为true,则本地签名者对给定地址进行投票,以将其包括在授权签名者集中。如果auth
设置为false
,则投票反对该地址。
客户 | 方法调用 |
---|---|
Console | clique.propose(address, auth) |
RPC | {"method": "clique_propose", "params": [address, auth]} |
clique_discard
此方法删除当前正在运行的投标。签名者将不会对该地址再投票(赞成或反对)。
客户 | 方法调用 |
---|---|
Console | clique.discard(address) |
RPC | {"method": "clique_discard", "params": [address]} |
clique_status
这是一种调试方法,可返回有关最后64个块的签名者活动的统计信息。返回的对象包含以下字段:
inturnPercent
:依次签名的块百分比sealerActivity
:包含签名者地址及其签名的块数的对象numBlocks
:分析的块数
客户 | 方法调用 |
---|---|
Console | clique.status() |
RPC | {"method": "clique_status", "params": [} |
例:
1 | > clique.status() |
调试命名空间
通过该debug
API,您可以访问几种非标准的RPC方法,从而可以在运行时检查,调试和设置某些调试标志。
debug_backtraceAt
设置日志回溯位置。当设置了backtrace位置并在该位置发出日志消息时,执行log语句的goroutine堆栈将被打印到stderr。
该位置指定为:
。
客户 | 方法调用 |
---|---|
Console | debug.backtraceAt(string) |
RPC | {"method": "debug_backtraceAt", "params": [string]} |
例:
1 | > debug.backtraceAt("server.go:443") |
debug_blockProfile
在给定的时间段内打开块分析,并将配置文件数据写入磁盘。它使用1的配置文件速率来获取最准确的信息。如果需要不同的速率,请设置速率并使用手动写入配置文件 debug_writeBlockProfile
。
客户 | 方法调用 |
---|---|
Console | debug.blockProfile(file, seconds) |
RPC | {"method": "debug_blockProfile", "params": [string, number]} |
debug_cpuProfile
在给定的时间内打开CPU性能分析,并将配置文件数据写入磁盘。
客户 | 方法调用 |
---|---|
Console | debug.cpuProfile(file, seconds) |
RPC | {"method": "debug_cpuProfile", "params": [string, number]} |
debug_dumpBlock
检索与块编号相对应的状态,并返回帐户列表(包括存储和代码)。
客户 | 方法调用 |
---|---|
Go | debug.DumpBlock(number uint64) (state.World, error) |
Console | debug.traceBlockByHash(number, [options]) |
RPC | {"method": "debug_dumpBlock", "params": [number]} |
例
1 | > debug.dumpBlock(10) |
debug_gcStats
返回GC统计信息。
有关返回的对象的字段的信息,请参见https://golang.org/pkg/runtime/debug/#GCStats。
客户 | 方法调用 |
---|---|
Console | debug.gcStats() |
RPC | {"method": "debug_gcStats", "params": []} |
debug_getBlockRlp
按编号检索并返回RLP编码的块。
客户 | 方法调用 |
---|---|
Go | debug.GetBlockRlp(number uint64) (string, error) |
Console | debug.getBlockRlp(number, [options]) |
RPC | {"method": "debug_getBlockRlp", "params": [number]} |
参考:RLP
debug_goTrace
在给定的持续时间内打开Go运行时跟踪,并将跟踪数据写入磁盘。
客户 | 方法调用 |
---|---|
Console | debug.goTrace(file, seconds) |
RPC | {"method": "debug_goTrace", "params": [string, number]} |
debug_memStats
返回详细的运行时内存统计信息。
有关返回的对象的字段的信息,请参见https://golang.org/pkg/runtime/#MemStats。
客户 | 方法调用 |
---|---|
Console | debug.memStats() |
RPC | {"method": "debug_memStats", "params": []} |
debug_seedHash
按编号获取和检索块的种子哈希
客户 | 方法调用 |
---|---|
Go | debug.SeedHash(number uint64) (string, error) |
Console | debug.seedHash(number, [options]) |
RPC | {"method": "debug_seedHash", "params": [number]} |
debug_setHead
通过块号设置本地链的当前首部。请注意,这是一种破坏性行为,可能会严重损坏您的链条。使用时要格外小心。
客户 | 方法调用 |
---|---|
Go | debug.SetHead(number uint64) |
Console | debug.setHead(number) |
RPC | {"method": "debug_setHead", "params": [number]} |
参考: Ethash
debug_setBlockProfileRate
设置goroutine块概要文件数据收集的速率(以样本/秒为单位)。非零速率启用块分析,将其设置为零将停止配置文件。收集的配置文件数据可以使用写入debug_writeBlockProfile
。
客户 | 方法调用 |
---|---|
Console | debug.setBlockProfileRate(rate) |
RPC | {"method": "debug_setBlockProfileRate", "params": [number]} |
debug_stacks
返回所有goroutine堆栈的打印表示形式。请注意,此方法的web3包装器负责打印,并且不返回字符串。
客户 | 方法调用 |
---|---|
Console | debug.stacks() |
RPC | {"method": "debug_stacks", "params": []} |
debug_startCPUProfile
无限期打开CPU配置文件,写入给定文件。
客户 | 方法调用 |
---|---|
Console | debug.startCPUProfile(file) |
RPC | {"method": "debug_startCPUProfile", "params": [string]} |
debug_startGoTrace
开始将Go运行时跟踪信息写入给定文件。
客户 | 方法调用 |
---|---|
Console | debug.startGoTrace(file) |
RPC | {"method": "debug_startGoTrace", "params": [string]} |
debug_stopCPUProfile
停止正在进行的CPU配置文件。
客户 | 方法调用 |
---|---|
Console | debug.stopCPUProfile() |
RPC | {"method": "debug_stopCPUProfile", "params": []} |
debug_stopGoTrace
停止编写Go运行时跟踪。
客户 | 方法调用 |
---|---|
Console | debug.startGoTrace(file) |
RPC | {"method": "debug_stopGoTrace", "params": []} |
debug_traceBlock
该traceBlock
方法将返回此块中包括的所有事务的所有已调用操作码的完整堆栈跟踪。注意,此块的父级必须存在,否则将失败。
客户 | 方法调用 |
---|---|
Go | debug.TraceBlock(blockRlp []byte, config. *vm.Config) BlockTraceResult |
Console | debug.traceBlock(tblockRlp, [options]) |
RPC | {"method": "debug_traceBlock", "params": [blockRlp, {}]} |
参考: RLP
例
1 | > debug.traceBlock("0xblock_rlp") |
debug_traceBlockByNumber
与debug_traceBlock相似,traceBlockByNumber
接受一个块号并重播数据库中已经存在的块。
客户 | 方法调用 |
---|---|
Go | debug.TraceBlockByNumber(number uint64, config. *vm.Config) BlockTraceResult |
Console | debug.traceBlockByNumber(number, [options]) |
RPC | {"method": "debug_traceBlockByNumber", "params": [number, {}]} |
参考: RLP
debug_traceBlockByHash
与debug_traceBlock相似,traceBlockByHash
接受块哈希并重播数据库中已经存在的块。
客户 | 方法调用 |
---|---|
Go | debug.TraceBlockByHash(hash common.Hash, config. *vm.Config) BlockTraceResult |
Console | debug.traceBlockByHash(hash, [options]) |
RPC | {"method": "debug_traceBlockByHash", "params": [hash {}]} |
参考: RLP
debug_traceBlockFromFile
与debug_traceBlock相似,traceBlockFromFile
接受包含该块的RLP的文件。
客户 | 方法调用 |
---|---|
Go | debug.TraceBlockFromFile(fileName string, config. *vm.Config) BlockTraceResult |
Console | debug.traceBlockFromFile(fileName, [options]) |
RPC | {"method": "debug_traceBlockFromFile", "params": [fileName, {}]} |
参考: RLP
debug_standardTraceBlockToFile
首次实现基于JS的跟踪(见下文)时,预期的用例是启用长时间运行的跟踪器,这些跟踪器可以通过订阅通道将结果流回。此方法的工作方式略有不同。(有关详细信息,请参阅PR)
- 它在执行期间将输出流传输到磁盘,以免消耗节点上的内存使用量
- 它
jsonl
用作输出格式(允许流式传输) - 使用跨客户端标准化输出,即所谓的“标准json”
- 用途
op
为操作码的字符串表示,而不是op
/opName
对数字/串,和其他小simlar差异。 - 有
refund
- 将内存表示为连续的数据块,而不是
32
像-byte段这样的列表debug_traceTransaction
- 用途
这意味着该方法仅对控制该节点的调用者“有用”,至少足以在事发后从文件系统中读取伪像。
该方法可用于将特定事务转出给定块:
1 | > debug.standardTraceBlockToFile("0x0bbe9f1484668a2bf159c63f0cf556ed8c8282f99e3ffdb03ad2175a863bca63", {txHash:"0x4049f61ffbb0747bb88dc1c85dd6686ebf225a3c10c282c45a8e0c644739f7e9", disableMemory:true}) |
或某个区块中的所有TX:
1 | > debug.standardTraceBlockToFile("0x0bbe9f1484668a2bf159c63f0cf556ed8c8282f99e3ffdb03ad2175a863bca63", {disableMemory:true}) |
使用命名标准在临时位置创建文件block_---
。每个操作码都会立即流到文件,除了os正常进行的缓冲外,没有缓冲缓冲。
在服务器端,当重新生成历史状态时,它还会添加一些更多信息,即required historical state is not avaiable
遇到reexec-number 时,以便用户可以尝试增加该设置。它还打印出剩余的块,直到到达目标:
1 | INFO [10-15|13:48:25.263] Regenerating historical state block=2385959 target=2386012 remaining=53 elapsed=3m30.990537767s |
该options
如下:
1 | type StdTraceConfig struct { |
debug_standardTraceBadBlockToFile
此方法与相似debug_standardTraceBlockToFile
,但可用于获取有关已被拒绝为无效(由于某种原因)的块的信息。
debug_traceTransaction
OBS在大多数情况下,debug.standardTraceBlockToFile
更适合于跟踪!
的traceTransaction
调试方法将尝试,因为它是在网络上执行以完全相同的方式来运行事务。在最终尝试执行与给定哈希对应的事务之前,它将重放在此之前可能已执行的任何事务。
除了事务的哈希值,您还可以给它一个辅助的可选参数,它指定此特定调用的选项。可能的选项是:
disableStorage
:BOOL
。将此设置为true将禁用存储捕获(默认= false)。disableMemory
:BOOL
。将此设置为true将禁用内存捕获(默认= false)。disableStack
:BOOL
。将此设置为true将禁用堆栈捕获(默认= false)。tracer
:STRING
。设置此选项将启用基于JavaScript的事务跟踪,如下所述。如果设置,则前四个参数将被忽略。timeout
:STRING
。替代基于JavaScript的跟踪调用的默认超时5秒。有效值在此处描述。
客户 | 方法调用 |
---|---|
Go | debug.TraceTransaction(txHash common.Hash, logger *vm.LogConfig) (*ExecutionResurt, error) |
Console | debug.traceTransaction(txHash, [options]) |
RPC | {"method": "debug_traceTransaction", "params": [txHash, {}]} |
例
1 | > debug.traceTransaction("0x2059dd53ecac9827faad14d364f9e04b1d5fe5b506e3acc886eff7a6f88a696a") |
基于JavaScript的跟踪
tracer
在第二个参数中指定选项将启用基于JavaScript的跟踪。在此模式下,tracer
被解释为一个JavaScript表达式,该表达式应使用(至少)两个方法(名为step
和)对一个对象求值result
。
step
是一个带有两个参数log和db的函数,该函数针对EVM的每个步骤或在跟踪指定事务时发生错误时被调用。
log
具有以下字段:
pc
:编号,当前程序计数器op
:对象,一个表示当前操作码的OpCode对象gas
:数量,剩余气体量gasPrice
:数量,每单位燃气的单位为单位的成本memory
:对象,表示合同的内存空间的结构stack
:array [big.Int],EVM执行堆栈depth
:执行深度account
:执行当前操作的帐户的地址err
:如果发生错误,则有关该错误的信息
如果err
为非null,则应忽略所有其他字段。
为了提高效率,同一log
对象在每个执行步骤中都被重用,并用当前值进行更新;确保将要保留的值复制到当前调用之外。例如,此步骤功能将不起作用:
1 | function(log) { |
但是此步骤功能将:
1 | function(log) { |
log.op
具有以下方法:
isPush()
-如果操作码为PUSHn,则返回truetoString()
-返回操作码的字符串表示形式toNumber()
-返回操作码的编号
log.memory
具有以下方法:
slice(start, stop)
-将指定的内存段作为字节片返回length()
-返回内存的长度
log.stack
具有以下方法:
peek(idx)
-从堆栈的顶部返回第idx个元素(0是最顶部的元素)为big.Intlength()
-返回堆栈中的元素数
db
具有以下方法:
getBalance(address)
-返回big.Int
具有指定帐户余额的getNonce(address)
-返回带有指定帐户随机数的数字getCode(address)
-返回带有指定帐户代码的字节片getState(address, hash)
-返回指定帐户和指定哈希的状态值exists(address)
-如果指定的地址存在,则返回true
第二个函数’result’不带任何参数,并且期望返回JSON可序列化的值以返回到RPC调用程序。
如果step函数在任何时候抛出异常或执行非法操作,则将不会在任何其他VM步骤上调用它,并且错误将返回给调用方。
请注意,有几个值是Golang big.Int对象,而不是JavaScript数字或JS bigints。因此,它们具有与godocs中描述的相同的界面。它们默认的序列化为JSON是一个Javascript数字。要序列化大量数字,请准确调用.String()
它们。为方便起见,big.NewInt(x)
提供了,并将uint转换为Go BigInt。
用法示例,仅在每个CALL操作码处返回堆栈的顶部元素:
1 | debug.traceTransaction(txhash, {tracer: '{data: [], fault: function(log) {}, step: function(log) { if(log.op.toString() == "CALL") this.data.push(log.stack.peek(0)); }, result: function() { return this.data; }}'}); |
debug_verbosity
设置日志记录的详细信息上限。将打印级别达到并包括给定级别的日志消息。
可以使用来提高单个软件包和源文件的详细程度debug_vmodule
。
客户 | 方法调用 |
---|---|
Console | debug.verbosity(level) |
RPC | {"method": "debug_vmodule", "params": [number]} |
debug_vmodule
设置日志记录的详细模式。
客户 | 方法调用 |
---|---|
Console | debug.vmodule(string) |
RPC | {"method": "debug_vmodule", "params": [string]} |
例子
如果要查看来自特定Go包(目录)和所有子目录的消息,请使用:
1 | > debug.vmodule("eth/*=6") |
如果要将消息限制为特定的程序包(例如p2p),但排除子目录,请使用:
1 | > debug.vmodule("p2p=6") |
如果要查看来自特定源文件的日志消息,请使用
1 | > debug.vmodule("server.go=6") |
您可以组成这些基本模式。如果要在eth(eth / peer.go,eth / downloader / peer.go)之下的包中查看来自peer.go的所有输出,以及在级别<= 5时从p2p包获得的输出,请使用:
1 | debug.vmodule("eth/*/peer.go=6,p2p=5") |
debug_writeBlockProfile
将goroutine阻止配置文件写入给定文件。
客户 | 方法调用 |
---|---|
Console | debug.writeBlockProfile(file) |
RPC | {"method": "debug_writeBlockProfile", "params": [string]} |
debug_writeMemProfile
将分配配置文件写入给定文件。请注意,无法通过API来设置分析速率,必须在命令行中使用--memprofilerate
标志来设置分析速率。
客户 | 方法调用 |
---|---|
Console | debug.writeMemProfile(file string) |
RPC | {"method": "debug_writeBlockProfile", "params": [string]} |
eth命名空间
Geth提供了对标准“ eth” JSON-RPC名称空间的几个扩展。
这些方法用于通过订阅进行的实时事件。有关更多信息,请参见订阅文档。
eth_call
立即执行新的消息调用,而无需在区块链上创建事务。该eth_call
方法可用于查询内部合同状态,执行编码到合同中的验证,甚至可以测试不实时运行交易的效果。
参量
该方法采用3个参数:一个以只读模式执行的未签名事务对象;执行调用的程序段号;以及可选的状态覆盖集,以允许针对修改后的链状态执行调用。
1.- Object
交易调用对象
该交易调用对象是强制性的,包含了所有必要的参数执行只读EVM合同法。
领域 | 类型 | 字节数 | 可选的 | 描述 |
---|---|---|---|---|
from |
Address |
20 | 是 | 模拟已发送交易的地址。默认为本地密钥库中的第一个帐户,0x00..0 如果没有可用的本地帐户,则为地址。 |
to |
Address |
20 | 没有 | 交易发送到的地址。 |
gas |
Quantity |
<8 | 是 | 代码执行的最大气体余量,可以避免无限循环。默认为2^63 或节点运算符通过指定的任何值--rpc.gascap 。 |
gasPrice |
Quantity |
<32 | 是 | wei 在执行期间模拟为每单位天然气支付的数量。默认为1 gwei 。 |
value |
Quantity |
<32 | 是 | 量wei 来模拟与交易一起发送。默认为0 。 |
data |
Binary |
任何 | 是 | 二进制数据发送到目标合同。通常,方法签名的4字节哈希值后跟ABI编码的参数。有关详细信息,请参阅以太坊合约ABI。 |
例:
1 | { |
2. Quantity | Tag
-块数或字符串latest
或pending
的块号是强制性的,并且限定针对其指定的事务应该被执行的上下文(状态)。无法对重组后的块执行调用;或大于128的块(除非该节点是归档节点)。
3.- Object
状态替代集
的状态覆写集是一个可选的地址到状态映射,其中每个条目指定一些状态之前执行呼叫被短暂地覆盖。每个地址都映射到一个包含以下内容的对象:
领域 | 类型 | 字节数 | 可选的 | 描述 |
---|---|---|---|---|
balance |
Quantity |
<32 | 是 | 在执行呼叫之前为帐户设置假余额。 |
nonce |
Quantity |
<8 | 是 | 在执行呼叫之前,先为帐户设置伪随机数。 |
code |
Binary |
任何 | 是 | 伪造EVM字节码以在执行调用之前注入帐户。 |
state |
Object |
任何 | 是 | 伪造的键值映射可在执行调用之前覆盖帐户存储中的所有插槽。 |
stateDiff |
Object |
任何 | 是 | 伪造的键值映射可在执行调用之前覆盖帐户存储中的各个插槽。 |
状态覆盖集的目标有很多:
- DApp可以使用它来减少需要在链上部署的合同代码的数量。可以简单地返回内部状态或执行预定义验证的代码可以保持脱链状态,并按需提供给节点。
- 通过使用自定义方法扩展部署在链上的代码并调用它们,可以将其用于智能合约分析。这避免了必须下载并重建沙箱中的整个状态以针对其运行自定义代码。
- 通过有选择地重写某些代码或状态并查看执行方式如何变化,可以将其用于调试已部署的大型合同套件中的智能合同。可能需要专门的工具。
例:
1 | { |
返回值
该方法返回一个Binary
包含执行的合同调用的返回值的单一对象。
简单的例子
通过在localhost(geth --rinkeby --rpc
)上公开了带有RPC的同步Rinkeby节点,我们可以对Checkpoint Oracle 进行调用以检索管理员列表:
1 | $ curl --data '{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},"latest"],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8545 |
结果是以太坊ABI编码的帐户列表:
1 | { |
仅出于完整性考虑,解码后的响应为:
1 | 0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3, |
覆盖示例
上面的简单示例显示了如何调用链上智能合约已经公开的方法。如果我们想访问一些未公开的数据怎么办?
我们可以 使用保留相同字段(以保留相同存储布局)的 原始检查点Oracle合同,但包含不同方法集的一个合同:
1 | pragma solidity ^0.5.10; |
通过在localhost(geth --rinkeby --rpc
)上公开了带有RPC的同步Rinkeby节点,我们可以对实时Checkpoint Oracle进行调用,但是可以使用我们自己的版本覆盖其字节代码,该版本具有用于投票阈值字段的访问器:
1 | $ curl --data '{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x0be5b6ba"}, "latest", {"0xebe8efa441b9302a0d7eaecc277c09d20d684540": {"code":"0x6080604052348015600f57600080fd5b506004361060285760003560e01c80630be5b6ba14602d575b600080fd5b60336045565b60408051918252519081900360200190f35b6007549056fea265627a7a723058206f26bd0433456354d8d1228d8fe524678a8aeeb0594851395bdbd35efc2a65f164736f6c634300050a0032"}}],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8545 |
结果是以太坊ABI编码的阈值编号:
1 | { |
仅出于完整性考虑,解码后的响应为:2
。
les命名空间
该les
API可让您管理LES服务器设置,包括客户端参数和优先客户端的付款设置。它还提供了在服务器和客户端模式下查询检查点信息的功能。
les_serverInfo
获取有关当前已连接以及允许的总/单独连接容量的信息。
客户 | 方法调用 |
---|---|
les.ServerInfo() map[string]interface{} |
|
Console | les.serverInfo() |
RPC | {"method": "les_serverInfo", "params": []} |
例
1 | > les.serverInfo |
les_clientInfo
如果指定的客户列表或ID列表为空,则获取所有指定客户列表上的所有客户信息(联系,余额,定价)。
客户 | 方法调用 |
---|---|
les.ClientInfo(ids []enode.ID) map[enode.ID]map[string]interface{} |
|
Console | les.clientInfo([id, ...]) |
RPC | {"method": "les_clientInfo", "params": [[id, ...]]} |
例
1 | > les.clientInfo([]) |
les_priorityClientInfo
获取有关指定ID范围内正余额(start
包括(stop
不包括))的客户的单个客户信息。如果stop
为零,则返回结果,直到最后一个现有余额输入。maxCount
限制返回结果的数量。如果达到计数限制,但该范围内有更多ID,则结果中将包含第一个缺少的ID,并为其分配一个空值。
客户 | 方法调用 |
---|---|
Go | les.PriorityClientInfo(start, stop enode.ID, maxCount int) map[enode.ID]map[string]interface{} |
Console | les.priorityClientInfo(id, id, number) |
RPC | {"method": "les_priorityClientInfo", "params": [id, id, number]} |
例
1 | > les.priorityClientInfo("0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", 100) |
les_addBalance
将签名的值添加到指定客户端的令牌余额中并更新其meta
标签。余额不能低于零或超过零2^^63-1
。返回更新前后的余额值。该meta
标签可用于存储序列号或对上次处理的传入付款,令牌到期信息,其他货币余额或任何特定于应用程序的其他信息的引用。
客户 | 方法调用 |
---|---|
les.AddBalance(id enode.ID, value int64, meta string) ([2]uint64, error)} |
|
Console | les.addBalance(id, number, string) |
RPC | {"method": "les_addBalance", "params": [id, number, string]} |
例
1 | > les.addBalance("0x6a47fe7bb23fd335df52ef1690f37ab44265a537b1d18eb616a3e77f898d9e77", 1000000000, "qwerty") |
les_setClientParams
如果ID列表为空,请为指定的已连接客户端列表或所有已连接客户端设置容量和价格因素。
客户 | 方法调用 |
---|---|
Go | les.SetClientParams(ids []enode.ID, params map[string]interface{}) error |
Console | les.setClientParams([id, ...], {string: value, ...}) |
RPC | {"method": "les_setClientParams", "params": [[id, ...], {string: value, ...}]} |
例
1 | > les.setClientParams(["0x6a47fe7bb23fd335df52ef1690f37ab44265a537b1d18eb616a3e77f898d9e77"], { |
les_setDefaultParams
为后续连接的客户设置默认定价因子。
客户 | 方法调用 |
---|---|
Go | les.SetDefaultParams(params map[string]interface{}) error |
Console | les.setDefaultParams({string: value, ...}) |
RPC | {"method": "les_setDefaultParams", "params": [{string: value, ...}]} |
例
1 | > les.setDefaultParams({ |
les_latestCheckpoint
获取最新已知检查点的索引和哈希。
客户 | 方法调用 |
---|---|
les.LatestCheckpoint() ([4]string, error) |
|
Console | les.latestCheckpoint() |
RPC | {"method": "les_latestCheckpoint", "params": []} |
例
1 | > les.latestCheckpoint |
les_getCheckpoint
通过索引获取检查点哈希。
客户 | 方法调用 |
---|---|
Go | les.GetCheckpoint(index uint64) ([3]string, error) |
Console | les.getCheckpoint(number) |
RPC | {"method": "les_getCheckpoint", "params": [number]} |
例
1 | > les.getCheckpoint(256) |
les_getCheckpointContractAddress
获取检查点Oracle合同的地址。
客户 | 方法调用 |
---|---|
Go | les.GetCheckpointContractAddress() (string, error) |
Console | les.checkpointContractAddress() |
RPC | {"method": "les_getCheckpointContractAddress", "params": []} |
例
1 | > les.checkpointContractAddress |
矿工命名空间
该miner
API使您可以远程控制节点的挖掘操作并设置各种挖掘特定的设置。
miner_getHashrate
获得以H / s为单位的哈希率(每秒哈希操作)。
客户 | 方法调用 |
---|---|
Console | miner.getHashrate() |
RPC | {"method": "miner_getHashrate", "params": []} |
miner_setExtra
设置矿工阻止时矿工可以包括的额外数据。上限为32个字节。
客户 | 方法调用 |
---|---|
Go | miner.setExtra(extra string) (bool, error) |
Console | miner.setExtra(string) |
RPC | {"method": "miner_setExtra", "params": [string]} |
miner_setGasPrice
设置采矿交易时的最低可接受天然气价格。低于此限制的任何交易都将从挖掘过程中排除。
客户 | 方法调用 |
---|---|
Go | miner.setGasPrice(number *rpc.HexNumber) bool |
Console | miner.setGasPrice(number) |
RPC | {"method": "miner_setGasPrice", "params": [number]} |
miner_start
使用给定数量的线程启动CPU挖掘过程,并在需要时生成新的DAG。
客户 | 方法调用 |
---|---|
Go | miner.Start(threads *rpc.HexNumber) (bool, error) |
Console | miner.start(number) |
RPC | {"method": "miner_start", "params": [number]} |
miner_stop
停止CPU挖掘操作。
客户 | 方法调用 |
---|---|
Go | miner.Stop() bool |
Console | miner.stop() |
RPC | {"method": "miner_stop", "params": []} |
miner_setEtherbase
设置以太坊,挖矿奖励将运往此。
客户 | 方法调用 |
---|---|
Go | miner.SetEtherbase(common.Address) bool |
Console | miner.setEtherbase(address) |
RPC | {"method": "miner_setEtherbase", "params": [address]} |
个人命名空间
个人API管理密钥存储区中的私钥。
personal_importRawKey
将给定的未加密私钥(十六进制字符串)导入密钥存储区,并使用密码对其进行加密。
返回新帐户的地址。
客户 | 方法调用 |
---|---|
Console | personal.importRawKey(keydata, passphrase) |
RPC | {"method": "personal_importRawKey", "params": [string, string]} |
personal_list帐户
返回密钥库中所有密钥的所有以太坊账户地址。
客户 | 方法调用 |
---|---|
Console | personal.listAccounts |
RPC | {"method": "personal_listAccounts", "params": []} |
例
1 | > personal.listAccounts |
personal_lock帐户
从内存中删除具有给定地址的私钥。该帐户不能再用于发送交易。
客户 | 方法调用 |
---|---|
Console | personal.lockAccount(address) |
RPC | {"method": "personal_lockAccount", "params": [string]} |
personal_new帐户
生成一个新的私钥并将其存储在密钥库目录中。密钥文件使用给定的密码加密。返回新帐户的地址。
在geth控制台上,newAccount
如果未提供密码作为参数,则将提示您输入密码。
客户 | 方法调用 |
---|---|
Console | personal.newAccount() |
RPC | {"method": "personal_newAccount", "params": [string]} |
例
1 | > personal.newAccount() |
密码也可以字符串形式提供。
1 | > personal.newAccount("h4ck3r") |
personal_unlock帐户
从密钥存储区使用给定的地址解密密钥。
使用JavaScript控制台时,密码短语和解锁持续时间都是可选的。如果未提供密码短语作为参数,则控制台将交互提示输入密码短语。
未加密的密钥将保留在内存中,直到解锁持续时间到期为止。如果解锁持续时间默认为300秒。明确的零秒持续时间将锁解锁,直到geth退出。
该账户可以使用eth_sign
,并eth_sendTransaction
同时被解锁。
客户 | 方法调用 |
---|---|
Console | personal.unlockAccount(address, passphrase, duration) |
RPC | {"method": "personal_unlockAccount", "params": [string, string, number]} |
例子
1 | > personal.unlockAccount("0x5e97870f263700f46aa00d967821199b9bc5a120") |
提供密码和解锁持续时间作为参数:
1 | > personal.unlockAccount("0x5e97870f263700f46aa00d967821199b9bc5a120", "foo", 30) |
如果要输入密码,并且stil覆盖默认的解锁持续时间,请null
以密码形式通过。
1 | > personal.unlockAccount("0x5e97870f263700f46aa00d967821199b9bc5a120", null, 30) |
personal_sendTransaction
验证给定的密码短语并提交交易。
事务与for相同,eth_sendTransaction
并且包含from
地址。如果密码短语可用于解密私钥,则将tx.from
验证登录到事务的签名,签名并发送到网络上。该帐户未在节点中全局解锁,因此无法在其他RPC调用中使用。
客户 | 方法调用 |
---|---|
Console | personal.sendTransaction(tx, passphrase) |
RPC | {"method": "personal_sendTransaction", "params": [tx, string]} |
请注意,在Geth 1.5之前,请使用personal_signAndSendTransaction
该名称,因为它是原始的介绍性名称,之后才重命名为当前的最终版本。
例子
1 | > var tx = {from: "0x391694e7e0b0cce554cb130d723a9d27458f9298", to: "0xafa3f8684e54059998bc3a7b0d2b0da075154d66", value: web3.toWei(1.23, "ether")} |
personal_sign
sign方法使用来计算以太坊特定的签名 sign(keccack256("\x19Ethereum Signed Message:\n" + len(message) + message)))
。
通过在消息中添加前缀,可以将计算出的签名识别为以太坊特定的签名。这样可以防止在恶意DApp可以签名任意数据(例如交易)并使用签名模拟受害者的情况下进行滥用。
请参阅ecRecover以验证签名。
客户 | 方法调用 |
---|---|
Console | personal.sign(message, account, [password]) |
RPC | {"method": "personal_sign", "params": [message, account, password]} |
例子
1 | > personal.sign("0xdeadbeaf", "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", "") |
personal_ecRecover
ecRecover
返回与用于计算中的签名的私钥关联的地址personal_sign
。
客户 | 方法调用 |
---|---|
Console | personal.ecRecover(message, signature) |
RPC | {"method": "personal_ecRecover", "params": [message, signature]} |
例子
1 | > personal.sign("0xdeadbeaf", "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", "") |
txpool命名空间
通过该txpool
API,您可以访问几种非标准RPC方法,以检查包含所有当前未决事务以及排队等待将来处理的事务的事务池的内容。
txpool_content
该content
检查性可以查询列出所有交易的具体细节目前尚待列入下一个块(一个或多个),以及正在计划在未来只有执行的人。
结果是具有两个字段pending
和的对象queued
。这些字段中的每一个都是关联数组,其中每个条目将原始地址映射到一批计划的事务。这些批次本身是将随机数与实际交易相关联的映射。
请注意,同一帐户和随机数可能有多个交易。如果用户播报了多种汽油配额(甚至完全不同的交易)的多种汽油,就会发生这种情况。
客户 | 方法调用 |
---|---|
Go | txpool.Content() (map[string]map[string]map[string]*RPCTransaction) |
Console | txpool.content |
RPC | {"method": "txpool_content"} |
例
1 | > txpool.content |
txpool_inspect
该inspect
检查性可以查询列出所有交易的文本摘要目前正在等待列入下一个块(一个或多个),以及正在计划在未来只有执行的人。这是专门为开发人员量身定制的方法,用于快速查看池中的事务并发现任何潜在问题。
结果是具有两个字段pending
和的对象queued
。这些字段中的每一个都是关联数组,其中每个条目将原始地址映射到一批计划的事务。这些批处理本身是将随机数与事务摘要字符串相关联的映射。
请注意,同一帐户和随机数可能有多个交易。如果用户播报了多种汽油配额(甚至完全不同的交易)的多种汽油,就会发生这种情况。
客户 | 方法调用 |
---|---|
Go | txpool.Inspect() (map[string]map[string]map[string]string) |
Console | txpool.inspect |
RPC | {"method": "txpool_inspect"} |
例
1 | > txpool.inspect |
txpool_status
该status
检查性,可以被询问的交易目前正等待列入下一个块(一个或多个)的数量,以及正在计划在未来只有执行的人。
结果是具有两个字段pending
和的对象queued
,每个字段都是一个计数器,代表该特定状态下的事务数。
客户 | 方法调用 |
---|---|
Go | txpool.Status() (map[string]*rpc.HexNumber) |
Console | txpool.status |
RPC | {"method": "txpool_status"} |
例
1 | > txpool.status |