Skip to content

Commit

Permalink
Block / REST explorer
Browse files Browse the repository at this point in the history
  • Loading branch information
arnetheduck committed Feb 17, 2023
1 parent a382498 commit d2221d1
Show file tree
Hide file tree
Showing 31 changed files with 1,701 additions and 6 deletions.
7 changes: 7 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,13 @@
path = vendor/nim-toml-serialization
url = https://github.com/status-im/nim-toml-serialization.git
ignore = untracked
[submodule "vendor/DOtherSide"]
path = vendor/DOtherSide
url = https://github.com/filcuc/DOtherSide.git
branch = master
[submodule "vendor/nimqml"]
path = vendor/nimqml
url = https://github.com/filcuc/nimqml.git
branch = master
[submodule "vendor/merge-testnets"]
path = vendor/merge-testnets
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,10 @@ force_build_alone_tools: | $(FORCE_BUILD_ALONE_TOOLS_DEPS)
# https://www.gnu.org/software/make/manual/html_node/Multiple-Rules.html#Multiple-Rules
# Already defined as a reult
nimbus_beacon_node: force_build_alone_tools
ngui/ngui: | build deps
+ echo -e $(BUILD_MSG) "build/$@" && \
MAKE="$(MAKE)" V="$(V)" $(ENV_SCRIPT) scripts/compile_nim_program.sh $@ "ngui.ngui.nim" $(NIM_PARAMS) && \
echo -e $(BUILD_END_MSG) "ngui/ngui"

clean_eth2_network_simulation_data:
rm -rf tests/simulation/data
Expand Down
25 changes: 19 additions & 6 deletions beacon_chain/spec/forks.nim
Original file line number Diff line number Diff line change
Expand Up @@ -772,28 +772,41 @@ template getForkedBlockField*(
of ConsensusFork.Capella: unsafeAddr x.capellaData.message.y
of ConsensusFork.EIP4844: unsafeAddr x.eip4844Data.message.y)[]

template signature*(x: ForkedSignedBeaconBlock |
template getForkedBodyField*(
x: ForkedSignedBeaconBlock |
ForkedMsgTrustedSignedBeaconBlock |
ForkedTrustedSignedBeaconBlock,
y: untyped): untyped =
# unsafeAddr avoids a copy of the field in some cases
(case x.kind
of ConsensusFork.Phase0: unsafeAddr x.phase0Data.message.body.y
of ConsensusFork.Altair: unsafeAddr x.altairData.message.body.y
of ConsensusFork.Bellatrix: unsafeAddr x.bellatrixData.message.body.y
of ConsensusFork.Capella: unsafeAddr x.capellaData.message.body.y
of ConsensusFork.EIP4844: unsafeAddr x.eip4844Data.message.body.y)[]

func signature*(x: ForkedSignedBeaconBlock |
ForkedMsgTrustedSignedBeaconBlock |
ForkedSignedBlindedBeaconBlock): ValidatorSig =
withBlck(x): blck.signature

template signature*(x: ForkedTrustedSignedBeaconBlock): TrustedSig =
func signature*(x: ForkedTrustedSignedBeaconBlock): TrustedSig =
withBlck(x): blck.signature

template root*(x: ForkedSignedBeaconBlock |
func root*(x: ForkedSignedBeaconBlock |
ForkedMsgTrustedSignedBeaconBlock |
ForkedTrustedSignedBeaconBlock): Eth2Digest =
withBlck(x): blck.root

template slot*(x: ForkedSignedBeaconBlock |
func slot*(x: ForkedSignedBeaconBlock |
ForkedMsgTrustedSignedBeaconBlock |
ForkedTrustedSignedBeaconBlock): Slot =
withBlck(x): blck.message.slot

template shortLog*(x: ForkedBeaconBlock | ForkedBlindedBeaconBlock): auto =
func shortLog*(x: ForkedBeaconBlock | ForkedBlindedBeaconBlock): auto =
withBlck(x): shortLog(blck)

template shortLog*(x: ForkedSignedBeaconBlock |
func shortLog*(x: ForkedSignedBeaconBlock |
ForkedMsgTrustedSignedBeaconBlock |
ForkedTrustedSignedBeaconBlock |
ForkedSignedBlindedBeaconBlock): auto =
Expand Down
65 changes: 65 additions & 0 deletions ngui/attestationlist.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import
std/[sequtils, tables],
NimQml,
../beacon_chain/spec/eth2_apis/rest_beacon_client,
../beacon_chain/spec/[eth2_merkleization, helpers],
./objecttablemodel, ./utils

type
AttestationInfo* = object
slot*: int
index*: int
beacon_block_root*: string
source_epoch*: int
source_root*: string
target_epoch*: int
target_root*: string
aggregation_bits*: string

proc toAttestationInfo*(v: Attestation): AttestationInfo =
AttestationInfo(
slot: v.data.slot.int,
index: v.data.index.int,
beacon_block_root: toBlockLink(v.data.beacon_block_root),
source_epoch: v.data.source.epoch.int,
source_root: toBlockLink(v.data.source.root),
target_epoch: v.data.target.epoch.int,
target_root: toBlockLink(v.data.target.root),
aggregation_bits: $v.aggregation_bits,
)

QtObject:
type AttestationList* = ref object of QAbstractTableModel
# TODO this could be a generic ObjectTableModel, except generics + method don't work..
data: ObjectTableModelImpl[AttestationInfo]

proc setup(self: AttestationList) = self.QAbstractTableModel.setup

proc delete(self: AttestationList) =
self.QAbstractTableModel.delete

proc newAttestationList*(data: seq[Attestation]): AttestationList =
new(result, delete)
result.data = ObjectTableModelImpl[AttestationInfo](items: data.mapIt(it.toAttestationInfo()))
result.setup

method rowCount(self: AttestationList, index: QModelIndex = nil): int =
self.data.rowCount(index)

method columnCount(self: AttestationList, index: QModelIndex = nil): int =
self.data.columnCount(index)

method headerData*(self: AttestationList, section: int, orientation: QtOrientation, role: int): QVariant =
self.data.headerData(section, orientation, role)

method data(self: AttestationList, index: QModelIndex, role: int): QVariant =
self.data.data(index, role)

method roleNames(self: AttestationList): Table[int, string] =
self.data.roleNames()

proc setNewData*(self: AttestationList, v: seq[Attestation]) =
self.data.setNewData(self, v.mapIt(it.toAttestationInfo()))

proc sort*(self: AttestationList, section: int) {.slot.} =
self.data.sort(self, section)
51 changes: 51 additions & 0 deletions ngui/attesterslashinglist.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import
std/[sequtils, tables],
NimQml,
../beacon_chain/spec/eth2_apis/rest_beacon_client,
../beacon_chain/spec/[helpers],
./objecttablemodel, ./utils

type
AttesterSlashingInfo* = object
info*: string

proc toAttesterSlashingInfo*(v: AttesterSlashing): AttesterSlashingInfo =
AttesterSlashingInfo(
info: $v
)

QtObject:
type AttesterSlashingList* = ref object of QAbstractTableModel
# TODO this could be a generic ObjectTableModel, except generics + method don't work..
data: ObjectTableModelImpl[AttesterSlashingInfo]

proc setup(self: AttesterSlashingList) = self.QAbstractTableModel.setup

proc delete(self: AttesterSlashingList) =
self.QAbstractTableModel.delete

proc newAttesterSlashingList*(data: openArray[AttesterSlashing]): AttesterSlashingList =
new(result, delete)
result.data = ObjectTableModelImpl[AttesterSlashingInfo](items: data.mapIt(it.toAttesterSlashingInfo()))
result.setup

method rowCount(self: AttesterSlashingList, index: QModelIndex = nil): int =
self.data.rowCount(index)

method columnCount(self: AttesterSlashingList, index: QModelIndex = nil): int =
self.data.columnCount(index)

method headerData*(self: AttesterSlashingList, section: int, orientation: QtOrientation, role: int): QVariant =
self.data.headerData(section, orientation, role)

method data(self: AttesterSlashingList, index: QModelIndex, role: int): QVariant =
self.data.data(index, role)

method roleNames(self: AttesterSlashingList): Table[int, string] =
self.data.roleNames()

proc setNewData*(self: AttesterSlashingList, v: openArray[AttesterSlashing]) =
self.data.setNewData(self, v.mapIt(it.toAttesterSlashingInfo()))

proc sort*(self: AttesterSlashingList, section: int) {.slot.} =
self.data.sort(self, section)
95 changes: 95 additions & 0 deletions ngui/blockmodel.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import
std/[sequtils, times],
NimQml,
../beacon_chain/spec/eth2_apis/rest_beacon_client,
../beacon_chain/spec/datatypes/[phase0, altair],
"."/[
attestationlist, depositlist, attesterslashinglist, proposerslashinglist,
voluntaryexitlist, utils]

QtObject:
type
BlockModel* = ref object of QObject
blck: ForkedSignedBeaconBlock
attestationsx: AttestationList
depositsx: DepositList
attester_slashingsx: AttesterSlashingList
proposer_slashingsx: ProposerSlashingList
voluntary_exitsx: VoluntaryExitList
genesis_time*: uint64

proc delete*(self: BlockModel) =
self.QObject.delete

proc setup*(self: BlockModel) =
self.QObject.setup

proc newBlockModel*(forked: ForkedSignedBeaconBlock, genesis_time: uint64): BlockModel =

let res = withBlck(forked): BlockModel(
blck: forked,
attestationsx: newAttestationList(blck.message.body.attestations.asSeq()),
depositsx: newDepositList(blck.message.body.deposits.mapIt(it.toDepositInfo())),
attester_slashingsx: newAttesterSlashingList(blck.message.body.attester_slashings.asSeq()),
proposer_slashingsx: newProposerSlashingList(blck.message.body.proposer_slashings.asSeq()),
voluntary_exitsx: newVoluntaryExitList(blck.message.body.voluntary_exits.asSeq()),
genesis_time: genesis_time,
)
res.setup()
res

proc `blck=`*(self: BlockModel, forked: ForkedSignedBeaconBlock) =
self.blck = forked
withBlck(forked):
self.attestationsx.setNewData(blck.message.body.attestations.asSeq())
self.depositsx.setNewData(blck.message.body.deposits.mapIt(it.toDepositInfo()))
self.attester_slashingsx.setNewData(blck.message.body.attester_slashings.asSeq())
self.proposer_slashingsx.setNewData(blck.message.body.proposer_slashings.asSeq())
self.voluntary_exitsx.setNewData(blck.message.body.voluntary_exits.asSeq())

proc slot*(self: BlockModel): int {.slot.} = getForkedBlockField(self.blck, slot).int
QtProperty[int] slot: read = slot

proc time*(self: BlockModel): string {.slot.} =
let t = self.genesis_time + getForkedBlockField(self.blck, slot) * SECONDS_PER_SLOT
$fromUnix(t.int64).utc
QtProperty[string] time: read = time

proc root*(self: BlockModel): string {.slot.} = toDisplayHex(self.blck.root.data)
QtProperty[string] root: read = root

proc proposer_index*(self: BlockModel): int {.slot.} = getForkedBlockField(self.blck, proposer_index).int
QtProperty[int] proposer_index: read = proposer_index

proc parent_root*(self: BlockModel): string {.slot.} = toBlockLink(getForkedBlockField(self.blck, parent_root))
QtProperty[string] parent_root: read = parent_root

proc state_root*(self: BlockModel): string {.slot.} = toDisplayHex(getForkedBlockField(self.blck, state_root).data)
QtProperty[string] state_root: read = state_root

proc randao_reveal*(self: BlockModel): string {.slot.} = toDisplayHex(getForkedBodyField(self.blck, randao_reveal))
QtProperty[string] randao_reveal: read = randao_reveal

proc eth1_data*(self: BlockModel): string {.slot.} = RestJson.encode(getForkedBodyField(self.blck, eth1_data), pretty=true)
QtProperty[string] eth1_data: read = eth1_data

proc graffiti*(self: BlockModel): string {.slot.} = $getForkedBodyField(self.blck, graffiti)
QtProperty[string] graffiti: read = graffiti

proc proposer_slashings*(self: BlockModel): QVariant {.slot.} = newQVariant(self.proposer_slashingsx)
QtProperty[QVariant] proposer_slashings: read = proposer_slashings

proc attester_slashings*(self: BlockModel): QVariant {.slot.} = newQVariant(self.attester_slashingsx)
QtProperty[QVariant] attester_slashings: read = attester_slashings

proc attestations*(self: BlockModel): QVariant {.slot.} = newQVariant(self.attestationsx)
QtProperty[QVariant] attestations: read = attestations

proc deposits*(self: BlockModel): QVariant {.slot.} = newQVariant(self.depositsx)
QtProperty[QVariant] deposits: read = deposits

proc voluntary_exits*(self: BlockModel): QVariant {.slot.} = newQVariant(self.voluntary_exitsx)
QtProperty[QVariant] voluntary_exits: read = voluntary_exits

proc signature*(self: BlockModel): string {.slot.} = toDisplayHex(self.blck.signature)
QtProperty[string] signature: read = signature
56 changes: 56 additions & 0 deletions ngui/depositlist.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import
std/[tables],
NimQml,
../beacon_chain/spec/datatypes/base,
./objecttablemodel, ./utils

type
DepositInfo* = object
pubkey*: string
withdrawal_credentials*: string
amount*: uint64
signature*: string

proc toDepositInfo*(v: Deposit): DepositInfo =
DepositInfo(
pubkey: toDisplayHex(v.data.pubkey.toRaw()),
withdrawal_credentials: toDisplayHex(v.data.withdrawal_credentials),
amount: v.data.amount,
signature: toDisplayHex(v.data.signature),
)

QtObject:
type DepositList* = ref object of QAbstractTableModel
# TODO this could be a generic ObjectTableModel, except generics + method don't work..
data: ObjectTableModelImpl[DepositInfo]

proc setup(self: DepositList) = self.QAbstractTableModel.setup

proc delete(self: DepositList) =
self.QAbstractTableModel.delete

proc newDepositList*(data: seq[DepositInfo]): DepositList =
new(result, delete)
result.data = ObjectTableModelImpl[DepositInfo](items: data)
result.setup

method rowCount(self: DepositList, index: QModelIndex = nil): int =
self.data.rowCount(index)

method columnCount(self: DepositList, index: QModelIndex = nil): int =
self.data.columnCount(index)

method headerData*(self: DepositList, section: int, orientation: QtOrientation, role: int): QVariant =
self.data.headerData(section, orientation, role)

method data(self: DepositList, index: QModelIndex, role: int): QVariant =
self.data.data(index, role)

method roleNames(self: DepositList): Table[int, string] =
self.data.roleNames()

proc setNewData*(self: DepositList, v: seq[DepositInfo]) =
self.data.setNewData(self, v)

proc sort*(self: DepositList, section: int) {.slot.} =
self.data.sort(self, section)
52 changes: 52 additions & 0 deletions ngui/epochmodel.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import NimQml

import
../beacon_chain/spec/eth2_apis/rest_beacon_client,
./slotlist

QtObject:
type
EpochModel* = ref object of QObject
client: RestClientRef
epoch: int
slotList: SlotList

proc delete*(self: EpochModel) =
self.QObject.delete

proc setup*(self: EpochModel) =
self.QObject.setup

proc newEpochModel*(client: RestClientRef, epoch: int): EpochModel =
let data = client.loadSlots(epoch.Epoch)
let res = EpochModel(client: client, epoch: epoch, slotList: newSlotList(data))
res.setup()
res

proc epoch*(self: EpochModel): int {.slot.} = self.epoch
proc epochChanged*(self: EpochModel, v: int) {.signal.}
QtProperty[int] epoch:
read = epoch
notify = epochChanged

proc getSlotList*(self: EpochModel): QVariant {.slot.} = newQVariant(self.slotList)
QtProperty[QVariant] slotList: read = getSlotList

proc setNewData*(self: EpochModel, epoch: int, data: seq[SlotInfo]) =
self.epoch = epoch
self.epochChanged(epoch)

self.slotList.setNewData(data)

proc reload(self: EpochModel) {.slot.} =
self.slotList.setNewData(self.client.loadSlots(self.epoch.Epoch))

proc next(self: EpochModel) {.slot.} =
self.epoch = self.epoch + 1
self.epochChanged(self.epoch)
self.reload() # TODO listen to epochchanged

proc prev(self: EpochModel) {.slot.} =
self.epoch = self.epoch - 1
self.epochChanged(self.epoch)
self.reload() # TODO listen to epochchanged

0 comments on commit d2221d1

Please sign in to comment.