2021-03-26 06:52:01 +00:00
|
|
|
# beacon_chain
|
2021-02-15 16:40:00 +00:00
|
|
|
# Copyright (c) 2018-2021 Status Research & Development GmbH
|
2020-10-27 09:00:57 +00:00
|
|
|
# Licensed and distributed under either of
|
|
|
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
|
|
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
|
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
|
2021-03-26 06:52:01 +00:00
|
|
|
{.push raises: [Defect].}
|
|
|
|
|
2020-10-27 09:00:57 +00:00
|
|
|
import
|
2021-01-26 11:52:00 +00:00
|
|
|
std/[deques, sequtils, sets],
|
2020-11-15 15:35:16 +00:00
|
|
|
chronos,
|
2020-10-27 09:00:57 +00:00
|
|
|
stew/byteutils,
|
2021-03-26 14:11:06 +00:00
|
|
|
json_rpc/servers/httpserver,
|
|
|
|
libp2p/protocols/pubsub/pubsubpeer,
|
2020-10-27 09:00:57 +00:00
|
|
|
|
2021-03-26 14:11:06 +00:00
|
|
|
".."/[
|
2021-10-19 14:09:26 +00:00
|
|
|
beacon_node, nimbus_binary_common, networking/eth2_network,
|
2021-03-26 14:11:06 +00:00
|
|
|
eth1/eth1_monitor, validators/validator_duties],
|
2021-06-23 14:43:18 +00:00
|
|
|
../spec/datatypes/base,
|
2021-08-12 13:08:20 +00:00
|
|
|
../spec/[forks],
|
2021-08-03 15:17:11 +00:00
|
|
|
./rpc_utils
|
2020-11-29 19:07:20 +00:00
|
|
|
|
2021-10-27 12:01:11 +00:00
|
|
|
when defined(chronosFutureTracking):
|
|
|
|
import stew/base10
|
|
|
|
|
2020-10-27 09:00:57 +00:00
|
|
|
logScope: topics = "nimbusapi"
|
|
|
|
|
|
|
|
type
|
|
|
|
RpcServer = RpcHttpServer
|
|
|
|
|
2020-11-29 19:07:20 +00:00
|
|
|
FutureInfo* = object
|
2021-10-27 12:01:11 +00:00
|
|
|
id*: string
|
|
|
|
child_id*: string
|
2020-11-29 19:07:20 +00:00
|
|
|
procname*: string
|
|
|
|
filename*: string
|
|
|
|
line*: int
|
|
|
|
state*: string
|
2020-11-15 15:35:16 +00:00
|
|
|
|
2021-03-26 06:52:01 +00:00
|
|
|
proc installNimbusApiHandlers*(rpcServer: RpcServer, node: BeaconNode) {.
|
2021-08-27 09:00:06 +00:00
|
|
|
raises: [Defect, CatchableError].} =
|
2020-10-28 18:51:38 +00:00
|
|
|
## Install non-standard api handlers - some of these are used by 3rd-parties
|
|
|
|
## such as eth2stats, pending a full REST api
|
2020-10-27 09:00:57 +00:00
|
|
|
rpcServer.rpc("getBeaconHead") do () -> Slot:
|
2021-06-01 11:13:40 +00:00
|
|
|
return node.dag.head.slot
|
2020-10-27 09:00:57 +00:00
|
|
|
|
|
|
|
rpcServer.rpc("getChainHead") do () -> JsonNode:
|
|
|
|
let
|
2021-06-01 11:13:40 +00:00
|
|
|
head = node.dag.head
|
2021-06-11 17:51:46 +00:00
|
|
|
finalized = getStateField(node.dag.headState.data, finalized_checkpoint)
|
2021-04-08 08:24:25 +00:00
|
|
|
justified =
|
2021-06-11 17:51:46 +00:00
|
|
|
getStateField(node.dag.headState.data, current_justified_checkpoint)
|
2020-10-27 09:00:57 +00:00
|
|
|
return %* {
|
|
|
|
"head_slot": head.slot,
|
|
|
|
"head_block_root": head.root.data.toHex(),
|
|
|
|
"finalized_slot": finalized.epoch * SLOTS_PER_EPOCH,
|
|
|
|
"finalized_block_root": finalized.root.data.toHex(),
|
|
|
|
"justified_slot": justified.epoch * SLOTS_PER_EPOCH,
|
|
|
|
"justified_block_root": justified.root.data.toHex(),
|
|
|
|
}
|
|
|
|
|
|
|
|
rpcServer.rpc("getSyncing") do () -> bool:
|
2020-10-28 18:51:38 +00:00
|
|
|
return node.syncManager.inProgress
|
2020-10-27 09:00:57 +00:00
|
|
|
|
|
|
|
rpcServer.rpc("getNetworkPeerId") do () -> string:
|
2020-10-28 18:51:38 +00:00
|
|
|
return $node.network.peerId()
|
2020-10-27 09:00:57 +00:00
|
|
|
|
|
|
|
rpcServer.rpc("getNetworkPeers") do () -> seq[string]:
|
|
|
|
for peerId, peer in node.network.peerPool:
|
|
|
|
result.add $peerId
|
|
|
|
|
2020-10-28 18:51:38 +00:00
|
|
|
rpcServer.rpc("getNodeVersion") do () -> string:
|
|
|
|
return "Nimbus/" & fullVersionStr
|
|
|
|
|
2020-10-27 09:00:57 +00:00
|
|
|
rpcServer.rpc("peers") do () -> JsonNode:
|
|
|
|
var res = newJObject()
|
|
|
|
var peers = newJArray()
|
|
|
|
for id, peer in node.network.peerPool:
|
|
|
|
peers.add(
|
|
|
|
%(
|
2021-10-21 11:01:29 +00:00
|
|
|
id: shortLog(peer.peerId),
|
2020-10-27 09:00:57 +00:00
|
|
|
connectionState: $peer.connectionState,
|
|
|
|
score: peer.score,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
res.add("peers", peers)
|
|
|
|
|
|
|
|
return res
|
2020-11-12 10:46:02 +00:00
|
|
|
|
|
|
|
rpcServer.rpc("setLogLevel") do (level: string) -> bool:
|
|
|
|
{.gcsafe.}: # It's probably not, actually. Hopefully we don't log from threads...
|
|
|
|
updateLogLevel(level)
|
|
|
|
return true
|
2020-11-15 15:35:16 +00:00
|
|
|
|
2021-03-26 17:42:20 +00:00
|
|
|
rpcServer.rpc("setGraffiti") do (graffiti: string) -> bool:
|
|
|
|
node.graffitiBytes = GraffitiBytes.init(graffiti)
|
|
|
|
return true
|
|
|
|
|
2020-11-20 14:42:04 +00:00
|
|
|
rpcServer.rpc("getEth1Chain") do () -> seq[Eth1Block]:
|
|
|
|
result = if node.eth1Monitor != nil:
|
2022-01-03 12:22:56 +00:00
|
|
|
mapIt(node.eth1Monitor.depositChainBlocks, it)
|
2020-11-20 14:42:04 +00:00
|
|
|
else:
|
|
|
|
@[]
|
|
|
|
|
|
|
|
rpcServer.rpc("getEth1ProposalData") do () -> BlockProposalEth1Data:
|
|
|
|
let
|
|
|
|
wallSlot = node.beaconClock.now.slotOrZero
|
|
|
|
head = node.doChecksAndGetCurrentHead(wallSlot)
|
|
|
|
|
2021-06-01 11:13:40 +00:00
|
|
|
let proposalState = assignClone(node.dag.headState)
|
|
|
|
node.dag.withState(proposalState[], head.atSlot(wallSlot)):
|
2021-06-11 17:51:46 +00:00
|
|
|
return node.getBlockProposalEth1Data(stateData.data)
|
2020-11-20 14:42:04 +00:00
|
|
|
|
2021-03-16 07:39:29 +00:00
|
|
|
rpcServer.rpc("debug_getChronosFutures") do () -> seq[FutureInfo]:
|
2020-11-29 19:07:20 +00:00
|
|
|
when defined(chronosFutureTracking):
|
2020-11-15 15:35:16 +00:00
|
|
|
var res: seq[FutureInfo]
|
|
|
|
|
|
|
|
for item in pendingFutures():
|
|
|
|
let loc = item.location[LocCreateIndex][]
|
2021-10-27 12:01:11 +00:00
|
|
|
let futureId = Base10.toString(item.id)
|
|
|
|
let childId =
|
|
|
|
if isNil(item.child): ""
|
|
|
|
else: Base10.toString(item.child.id)
|
2020-11-15 15:35:16 +00:00
|
|
|
res.add FutureInfo(
|
2021-10-27 12:01:11 +00:00
|
|
|
id: futureId,
|
|
|
|
child_id: childId,
|
2020-11-15 15:35:16 +00:00
|
|
|
procname: $loc.procedure,
|
|
|
|
filename: $loc.file,
|
|
|
|
line: loc.line,
|
|
|
|
state: $item.state
|
|
|
|
)
|
|
|
|
|
|
|
|
return res
|
2020-11-29 19:07:20 +00:00
|
|
|
else:
|
|
|
|
raise (ref CatchableError)(
|
|
|
|
msg: "Compile with '-d:chronosFutureTracking' to enable this request")
|
|
|
|
|
2021-03-16 07:39:29 +00:00
|
|
|
rpcServer.rpc("debug_getGossipSubPeers") do () -> JsonNode:
|
2020-11-29 19:07:20 +00:00
|
|
|
var res = newJObject()
|
|
|
|
var gossipsub = newJObject()
|
|
|
|
|
2021-03-16 07:39:29 +00:00
|
|
|
proc toNode(v: PubSubPeer, backoff: Moment): JsonNode =
|
2020-11-29 19:07:20 +00:00
|
|
|
%(
|
|
|
|
peerId: $v.peerId,
|
|
|
|
score: v.score,
|
|
|
|
iWantBudget: v.iWantBudget,
|
|
|
|
iHaveBudget: v.iHaveBudget,
|
|
|
|
outbound: v.outbound,
|
|
|
|
appScore: v.appScore,
|
2021-03-16 07:39:29 +00:00
|
|
|
behaviourPenalty: v.behaviourPenalty,
|
|
|
|
sendConnAvail: v.sendConn != nil,
|
|
|
|
closed: v.sendConn != nil and v.sendConn.closed,
|
|
|
|
atEof: v.sendConn != nil and v.sendConn.atEof,
|
|
|
|
address: if v.address.isSome():
|
|
|
|
$v.address.get()
|
|
|
|
else:
|
|
|
|
"<no address>",
|
|
|
|
backoff: $(backoff - Moment.now()),
|
|
|
|
agent: when defined(libp2p_agents_metrics):
|
|
|
|
v.shortAgent
|
|
|
|
else:
|
|
|
|
"unknown",
|
2020-11-29 19:07:20 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
for topic, v in node.network.pubsub.gossipsub:
|
|
|
|
var peers = newJArray()
|
2021-03-16 07:39:29 +00:00
|
|
|
let backoff = node.network.pubsub.backingOff.getOrDefault(topic)
|
2020-11-29 19:07:20 +00:00
|
|
|
for peer in v:
|
2021-03-16 07:39:29 +00:00
|
|
|
peers.add(peer.toNode(backOff.getOrDefault(peer.peerId)))
|
|
|
|
|
2020-11-29 19:07:20 +00:00
|
|
|
gossipsub.add(topic, peers)
|
|
|
|
|
|
|
|
res.add("gossipsub", gossipsub)
|
|
|
|
|
|
|
|
var mesh = newJObject()
|
|
|
|
for topic, v in node.network.pubsub.mesh:
|
|
|
|
var peers = newJArray()
|
2021-03-16 07:39:29 +00:00
|
|
|
let backoff = node.network.pubsub.backingOff.getOrDefault(topic)
|
2020-11-29 19:07:20 +00:00
|
|
|
for peer in v:
|
2021-03-16 07:39:29 +00:00
|
|
|
peers.add(peer.toNode(backOff.getOrDefault(peer.peerId)))
|
2020-11-29 19:07:20 +00:00
|
|
|
|
|
|
|
mesh.add(topic, peers)
|
|
|
|
|
|
|
|
res.add("mesh", mesh)
|
|
|
|
|
2021-03-16 07:39:29 +00:00
|
|
|
var coloc = newJArray()
|
|
|
|
for k, v in node.network.pubsub.peersInIP:
|
|
|
|
var a = newJObject()
|
|
|
|
var peers = newJArray()
|
|
|
|
for p in v:
|
|
|
|
peers.add(%($p))
|
|
|
|
a.add($k, peers)
|
|
|
|
coloc.add(a)
|
|
|
|
|
|
|
|
res.add("colocationPeers", coloc)
|
|
|
|
|
|
|
|
var stats = newJArray()
|
|
|
|
for peerId, pstats in node.network.pubsub.peerStats:
|
|
|
|
let
|
|
|
|
peer = node.network.pubsub.peers.getOrDefault(peerId)
|
|
|
|
null = isNil(peer)
|
|
|
|
connected = if null:
|
|
|
|
false
|
|
|
|
else :
|
|
|
|
peer.connected()
|
|
|
|
|
|
|
|
stats.add(%(
|
|
|
|
peerId: $peerId,
|
|
|
|
null: null,
|
|
|
|
connected: connected,
|
|
|
|
expire: $(pstats.expire - Moment.now()),
|
|
|
|
score: pstats.score
|
|
|
|
))
|
|
|
|
|
|
|
|
res.add("peerStats", stats)
|
|
|
|
|
|
|
|
var peers = newJArray()
|
|
|
|
for peerId, peer in node.network.pubsub.peers:
|
|
|
|
peers.add(%(
|
|
|
|
connected: peer.connected,
|
|
|
|
peerId: $peerId
|
|
|
|
))
|
|
|
|
|
|
|
|
res.add("allPeers", peers)
|
|
|
|
|
2020-11-29 19:07:20 +00:00
|
|
|
return res
|