Skip to content

Commit 85f4a60

Browse files
tersecarnetheduck
authored andcommitted
Block / REST explorer
1 parent 4e44027 commit 85f4a60

35 files changed

+1755
-9
lines changed

.gitmodules

+7
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,13 @@
199199
path = vendor/nim-toml-serialization
200200
url = https://github.com/status-im/nim-toml-serialization.git
201201
ignore = untracked
202+
[submodule "vendor/DOtherSide"]
203+
path = vendor/DOtherSide
204+
url = https://github.com/filcuc/DOtherSide.git
205+
branch = master
206+
[submodule "vendor/nimqml"]
207+
path = vendor/nimqml
208+
url = https://github.com/status-im/nimqml.git
202209
branch = master
203210
[submodule "vendor/gnosis-chain-configs"]
204211
path = vendor/gnosis-chain-configs

Makefile

+4
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,10 @@ force_build_alone_tools: | $(FORCE_BUILD_ALONE_TOOLS_DEPS)
485485
# https://www.gnu.org/software/make/manual/html_node/Multiple-Rules.html#Multiple-Rules
486486
# Already defined as a reult
487487
nimbus_beacon_node: force_build_alone_tools
488+
ngui/ngui: | build deps
489+
+ echo -e $(BUILD_MSG) "build/$@" && \
490+
MAKE="$(MAKE)" V="$(V)" $(ENV_SCRIPT) scripts/compile_nim_program.sh $@ "ngui.ngui.nim" $(NIM_PARAMS) && \
491+
echo -e $(BUILD_END_MSG) "ngui/ngui"
488492

489493
GOERLI_TESTNETS_PARAMS := \
490494
--tcp-port=$$(( $(BASE_PORT) + $(NODE_ID) )) \

beacon_chain/spec/eth2_apis/rest_validator_calls.nim

+23
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ import
1313

1414
export client, rest_types, eth2_rest_serialization
1515

16+
proc getAttesterDuties*(
17+
epoch: Epoch,
18+
body: seq[ValidatorIndex]
19+
): RestResponse[GetAttesterDutiesResponse] {.
20+
rest, endpoint: "/eth/v1/validator/duties/attester/{epoch}",
21+
meth: MethodPost.}
22+
## https://ethereum.github.io/beacon-APIs/#/Validator/getAttesterDuties
23+
1624
proc getAttesterDutiesPlain*(
1725
epoch: Epoch,
1826
body: seq[ValidatorIndex]
@@ -21,13 +29,28 @@ proc getAttesterDutiesPlain*(
2129
meth: MethodPost.}
2230
## https://ethereum.github.io/beacon-APIs/#/Validator/getAttesterDuties
2331

32+
proc getProposerDuties*(
33+
epoch: Epoch
34+
): RestResponse[GetProposerDutiesResponse] {.
35+
rest, endpoint: "/eth/v1/validator/duties/proposer/{epoch}",
36+
meth: MethodGet.}
37+
## https://ethereum.github.io/beacon-APIs/#/Validator/getProposerDuties
38+
2439
proc getProposerDutiesPlain*(
2540
epoch: Epoch
2641
): RestPlainResponse {.
2742
rest, endpoint: "/eth/v1/validator/duties/proposer/{epoch}",
2843
meth: MethodGet.}
2944
## https://ethereum.github.io/beacon-APIs/#/Validator/getProposerDuties
3045

46+
proc getSyncCommitteeDuties*(
47+
epoch: Epoch,
48+
body: seq[ValidatorIndex]
49+
): RestResponse[GetSyncCommitteeDutiesResponse] {.
50+
rest, endpoint: "/eth/v1/validator/duties/sync/{epoch}",
51+
meth: MethodPost.}
52+
## https://ethereum.github.io/beacon-APIs/#/Validator/getSyncCommitteeDuties
53+
3154
proc getSyncCommitteeDutiesPlain*(
3255
epoch: Epoch,
3356
body: seq[ValidatorIndex]

beacon_chain/spec/forks.nim

+28-9
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ type
180180
phase0.Attestation |
181181
electra.Attestation
182182

183+
ForkyAttesterSlashing* =
184+
phase0.AttesterSlashing |
185+
electra.AttesterSlashing
186+
183187
ForkedAttestation* = object
184188
case kind*: ConsensusFork
185189
of ConsensusFork.Phase0: phase0Data*: phase0.Attestation
@@ -630,9 +634,9 @@ template Forky*(
630634
kind: static ConsensusFork): auto =
631635
kind.SignedBeaconBlock
632636

633-
# Workaround method used for tests that involve walking through
634-
# `nim-eth2-scnarios`fork dirs, to be removed once Fulu is
635-
# included in new release.
637+
# Workaround method used for tests that involve walking through
638+
# `nim-eth2-scnarios`fork dirs, to be removed once Fulu is
639+
# included in new release.
636640
template withAllButFulu*(
637641
x: typedesc[ConsensusFork], body: untyped): untyped =
638642
static: doAssert ConsensusFork.high == ConsensusFork.Fulu
@@ -1276,28 +1280,43 @@ template getForkedBlockField*(
12761280
of ConsensusFork.Electra: unsafeAddr x.electraData.message.y
12771281
of ConsensusFork.Fulu: unsafeAddr x.fuluData.message.y)[]
12781282

1279-
template signature*(x: ForkedSignedBeaconBlock |
1283+
template getForkedBodyField*(
1284+
x: ForkedSignedBeaconBlock |
1285+
ForkedMsgTrustedSignedBeaconBlock |
1286+
ForkedTrustedSignedBeaconBlock,
1287+
y: untyped): untyped =
1288+
# unsafeAddr avoids a copy of the field in some cases
1289+
(case x.kind
1290+
of ConsensusFork.Phase0: unsafeAddr x.phase0Data.message.body.y
1291+
of ConsensusFork.Altair: unsafeAddr x.altairData.message.body.y
1292+
of ConsensusFork.Bellatrix: unsafeAddr x.bellatrixData.message.body.y
1293+
of ConsensusFork.Capella: unsafeAddr x.capellaData.message.body.y
1294+
of ConsensusFork.Deneb: unsafeAddr x.denebData.message.body.y
1295+
of ConsensusFork.Electra: unsafeAddr x.electraData.message.body.y
1296+
of ConsensusFork.Fulu: unsafeAddr x.fuluData.message.body.y)[]
1297+
1298+
func signature*(x: ForkedSignedBeaconBlock |
12801299
ForkedMsgTrustedSignedBeaconBlock |
12811300
ForkedSignedBlindedBeaconBlock): ValidatorSig =
12821301
withBlck(x): forkyBlck.signature
12831302

1284-
template signature*(x: ForkedTrustedSignedBeaconBlock): TrustedSig =
1303+
func signature*(x: ForkedTrustedSignedBeaconBlock): TrustedSig =
12851304
withBlck(x): forkyBlck.signature
12861305

1287-
template root*(x: ForkedSignedBeaconBlock |
1306+
func root*(x: ForkedSignedBeaconBlock |
12881307
ForkedMsgTrustedSignedBeaconBlock |
12891308
ForkedTrustedSignedBeaconBlock): Eth2Digest =
12901309
withBlck(x): forkyBlck.root
12911310

1292-
template slot*(x: ForkedSignedBeaconBlock |
1311+
func slot*(x: ForkedSignedBeaconBlock |
12931312
ForkedMsgTrustedSignedBeaconBlock |
12941313
ForkedTrustedSignedBeaconBlock): Slot =
12951314
withBlck(x): forkyBlck.message.slot
12961315

1297-
template shortLog*(x: ForkedBeaconBlock | ForkedBlindedBeaconBlock): auto =
1316+
func shortLog*(x: ForkedBeaconBlock | ForkedBlindedBeaconBlock): auto =
12981317
withBlck(x): shortLog(forkyBlck)
12991318

1300-
template shortLog*(x: ForkedSignedBeaconBlock |
1319+
func shortLog*(x: ForkedSignedBeaconBlock |
13011320
ForkedMsgTrustedSignedBeaconBlock |
13021321
ForkedTrustedSignedBeaconBlock |
13031322
ForkedSignedBlindedBeaconBlock): auto =

beacon_chain/spec/helpers.nim

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import
1313
# Status libraries
14+
std/times,
1415
stew/[byteutils, endians2, objects],
1516
nimcrypto/sha2,
1617
chronicles,

ngui/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
resources.cpp

ngui/attestationlist.nim

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import
2+
std/[sequtils, tables],
3+
NimQml,
4+
../beacon_chain/spec/eth2_apis/rest_beacon_client,
5+
../beacon_chain/spec/[eth2_merkleization, helpers],
6+
./objecttablemodel, ./utils
7+
8+
type
9+
AttestationInfo* = object
10+
slot*: int
11+
index*: int
12+
beacon_block_root*: string
13+
source_epoch*: int
14+
source_root*: string
15+
target_epoch*: int
16+
target_root*: string
17+
aggregation_bits*: string
18+
19+
proc toAttestationInfo*(v: ForkyAttestation): AttestationInfo =
20+
AttestationInfo(
21+
slot: v.data.slot.int,
22+
index: v.data.index.int,
23+
beacon_block_root: toBlockLink(v.data.beacon_block_root),
24+
source_epoch: v.data.source.epoch.int,
25+
source_root: toBlockLink(v.data.source.root),
26+
target_epoch: v.data.target.epoch.int,
27+
target_root: toBlockLink(v.data.target.root),
28+
aggregation_bits: $v.aggregation_bits,
29+
)
30+
31+
proc toAttestationInfo*(v: electra.Attestation): AttestationInfo =
32+
AttestationInfo(
33+
slot: v.data.slot.int,
34+
index: 0.int,
35+
beacon_block_root: toBlockLink(v.data.beacon_block_root),
36+
source_epoch: v.data.source.epoch.int,
37+
source_root: toBlockLink(v.data.source.root),
38+
target_epoch: v.data.target.epoch.int,
39+
target_root: toBlockLink(v.data.target.root),
40+
aggregation_bits: $v.aggregation_bits,
41+
)
42+
43+
QtObject:
44+
type AttestationList* = ref object of QAbstractTableModel
45+
# TODO this could be a generic ObjectTableModel, except generics + method don't work..
46+
data: ObjectTableModelImpl[AttestationInfo]
47+
48+
proc setup(self: AttestationList) = self.QAbstractTableModel.setup
49+
50+
proc delete(self: AttestationList) =
51+
self.QAbstractTableModel.delete
52+
53+
proc newAttestationList*(data: seq[ForkyAttestation]): AttestationList =
54+
new(result, delete)
55+
result.data = ObjectTableModelImpl[AttestationInfo](items: data.mapIt(it.toAttestationInfo()))
56+
result.setup
57+
58+
method rowCount(self: AttestationList, index: QModelIndex = nil): int =
59+
self.data.rowCount(index)
60+
61+
method columnCount(self: AttestationList, index: QModelIndex = nil): int =
62+
self.data.columnCount(index)
63+
64+
method headerData*(self: AttestationList, section: int, orientation: QtOrientation, role: int): QVariant =
65+
self.data.headerData(section, orientation, role)
66+
67+
method data(self: AttestationList, index: QModelIndex, role: int): QVariant =
68+
self.data.data(index, role)
69+
70+
method roleNames(self: AttestationList): Table[int, string] =
71+
self.data.roleNames()
72+
73+
proc setNewData*(self: AttestationList, v: seq[ForkyAttestation]) =
74+
self.data.setNewData(self, v.mapIt(it.toAttestationInfo()))
75+
76+
proc sort*(self: AttestationList, section: int) {.slot.} =
77+
self.data.sort(self, section)

ngui/attesterslashinglist.nim

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import
2+
std/[sequtils, tables],
3+
NimQml,
4+
../beacon_chain/spec/eth2_apis/rest_beacon_client,
5+
../beacon_chain/spec/[helpers],
6+
./objecttablemodel, ./utils
7+
8+
type
9+
AttesterSlashingInfo* = object
10+
info*: string
11+
12+
proc toAttesterSlashingInfo*(v: ForkyAttesterSlashing): AttesterSlashingInfo =
13+
AttesterSlashingInfo(
14+
info: $v
15+
)
16+
17+
QtObject:
18+
type AttesterSlashingList* = ref object of QAbstractTableModel
19+
# TODO this could be a generic ObjectTableModel, except generics + method don't work..
20+
data: ObjectTableModelImpl[AttesterSlashingInfo]
21+
22+
proc setup(self: AttesterSlashingList) = self.QAbstractTableModel.setup
23+
24+
proc delete(self: AttesterSlashingList) =
25+
self.QAbstractTableModel.delete
26+
27+
proc newAttesterSlashingList*(data: openArray[ForkyAttesterSlashing]): AttesterSlashingList =
28+
new(result, delete)
29+
result.data = ObjectTableModelImpl[AttesterSlashingInfo](items: data.mapIt(it.toAttesterSlashingInfo()))
30+
result.setup
31+
32+
method rowCount(self: AttesterSlashingList, index: QModelIndex = nil): int =
33+
self.data.rowCount(index)
34+
35+
method columnCount(self: AttesterSlashingList, index: QModelIndex = nil): int =
36+
self.data.columnCount(index)
37+
38+
method headerData*(self: AttesterSlashingList, section: int, orientation: QtOrientation, role: int): QVariant =
39+
self.data.headerData(section, orientation, role)
40+
41+
method data(self: AttesterSlashingList, index: QModelIndex, role: int): QVariant =
42+
self.data.data(index, role)
43+
44+
method roleNames(self: AttesterSlashingList): Table[int, string] =
45+
self.data.roleNames()
46+
47+
proc setNewData*(self: AttesterSlashingList, v: openArray[ForkyAttesterSlashing]) =
48+
self.data.setNewData(self, v.mapIt(it.toAttesterSlashingInfo()))
49+
50+
proc sort*(self: AttesterSlashingList, section: int) {.slot.} =
51+
self.data.sort(self, section)

ngui/blockmodel.nim

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import
2+
std/[sequtils, times],
3+
NimQml,
4+
../beacon_chain/spec/eth2_apis/rest_beacon_client,
5+
"."/[
6+
attestationlist, depositlist, attesterslashinglist, proposerslashinglist,
7+
voluntaryexitlist, utils]
8+
9+
QtObject:
10+
type
11+
BlockModel* = ref object of QObject
12+
blck: ForkedSignedBeaconBlock
13+
attestationsx: AttestationList
14+
depositsx: DepositList
15+
attester_slashingsx: AttesterSlashingList
16+
proposer_slashingsx: ProposerSlashingList
17+
voluntary_exitsx: VoluntaryExitList
18+
genesis_time*: uint64
19+
20+
proc delete*(self: BlockModel) =
21+
self.QObject.delete
22+
23+
proc setup*(self: BlockModel) =
24+
self.QObject.setup
25+
26+
proc newBlockModel*(forked: ForkedSignedBeaconBlock, genesis_time: uint64): BlockModel =
27+
let res = withBlck(forked): BlockModel(
28+
blck: forked,
29+
attestationsx: newAttestationList(forkyBlck.message.body.attestations.asSeq()),
30+
depositsx: newDepositList(forkyBlck.message.body.deposits.mapIt(it.toDepositInfo())),
31+
attester_slashingsx: newAttesterSlashingList(forkyBlck.message.body.attester_slashings.asSeq()),
32+
proposer_slashingsx: newProposerSlashingList(forkyBlck.message.body.proposer_slashings.asSeq()),
33+
voluntary_exitsx: newVoluntaryExitList(forkyBlck.message.body.voluntary_exits.asSeq()),
34+
genesis_time: genesis_time,
35+
)
36+
res.setup()
37+
res
38+
39+
proc `blck=`*(self: BlockModel, forked: ForkedSignedBeaconBlock) =
40+
self.blck = forked
41+
withBlck(forked):
42+
self.attestationsx.setNewData(forkyBlck.message.body.attestations.asSeq())
43+
self.depositsx.setNewData(forkyBlck.message.body.deposits.mapIt(it.toDepositInfo()))
44+
self.attester_slashingsx.setNewData(forkyBlck.message.body.attester_slashings.asSeq())
45+
self.proposer_slashingsx.setNewData(forkyBlck.message.body.proposer_slashings.asSeq())
46+
self.voluntary_exitsx.setNewData(forkyBlck.message.body.voluntary_exits.asSeq())
47+
48+
proc slot*(self: BlockModel): int {.slot.} = getForkedBlockField(self.blck, slot).int
49+
QtProperty[int] slot: read = slot
50+
51+
proc time*(self: BlockModel): string {.slot.} =
52+
let t = self.genesis_time + getForkedBlockField(self.blck, slot) * SECONDS_PER_SLOT
53+
$fromUnix(t.int64).utc
54+
QtProperty[string] time: read = time
55+
56+
proc root*(self: BlockModel): string {.slot.} = toDisplayHex(self.blck.root.data)
57+
QtProperty[string] root: read = root
58+
59+
proc proposer_index*(self: BlockModel): int {.slot.} = getForkedBlockField(self.blck, proposer_index).int
60+
QtProperty[int] proposer_index: read = proposer_index
61+
62+
proc parent_root*(self: BlockModel): string {.slot.} = toBlockLink(getForkedBlockField(self.blck, parent_root))
63+
QtProperty[string] parent_root: read = parent_root
64+
65+
proc state_root*(self: BlockModel): string {.slot.} = toDisplayHex(getForkedBlockField(self.blck, state_root).data)
66+
QtProperty[string] state_root: read = state_root
67+
68+
proc randao_reveal*(self: BlockModel): string {.slot.} = toDisplayHex(getForkedBodyField(self.blck, randao_reveal))
69+
QtProperty[string] randao_reveal: read = randao_reveal
70+
71+
proc eth1_data*(self: BlockModel): string {.slot.} = RestJson.encode(getForkedBodyField(self.blck, eth1_data), pretty=true)
72+
QtProperty[string] eth1_data: read = eth1_data
73+
74+
proc graffiti*(self: BlockModel): string {.slot.} = $getForkedBodyField(self.blck, graffiti)
75+
QtProperty[string] graffiti: read = graffiti
76+
77+
proc proposer_slashings*(self: BlockModel): QVariant {.slot.} = newQVariant(self.proposer_slashingsx)
78+
QtProperty[QVariant] proposer_slashings: read = proposer_slashings
79+
80+
proc attester_slashings*(self: BlockModel): QVariant {.slot.} = newQVariant(self.attester_slashingsx)
81+
QtProperty[QVariant] attester_slashings: read = attester_slashings
82+
83+
proc attestations*(self: BlockModel): QVariant {.slot.} = newQVariant(self.attestationsx)
84+
QtProperty[QVariant] attestations: read = attestations
85+
86+
proc deposits*(self: BlockModel): QVariant {.slot.} = newQVariant(self.depositsx)
87+
QtProperty[QVariant] deposits: read = deposits
88+
89+
proc voluntary_exits*(self: BlockModel): QVariant {.slot.} = newQVariant(self.voluntary_exitsx)
90+
QtProperty[QVariant] voluntary_exits: read = voluntary_exits
91+
92+
proc signature*(self: BlockModel): string {.slot.} = toDisplayHex(self.blck.signature)
93+
QtProperty[string] signature: read = signature

0 commit comments

Comments
 (0)