Skip to content

Commit

Permalink
show deposits on validator details page
Browse files Browse the repository at this point in the history
  • Loading branch information
pk910 committed Nov 29, 2024
1 parent 8a020ca commit 0f74f94
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 30 deletions.
10 changes: 10 additions & 0 deletions db/deposits.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,16 @@ func GetDepositTxsFiltered(offset uint64, limit uint32, finalizedBlock uint64, f
`)

filterOp := "WHERE"
if filter.MinIndex > 0 {
args = append(args, filter.MinIndex)
fmt.Fprintf(&sql, " %v deposit_index >= $%v", filterOp, len(args))
filterOp = "AND"
}
if filter.MaxIndex > 0 {
args = append(args, filter.MaxIndex)
fmt.Fprintf(&sql, " %v deposit_index <= $%v", filterOp, len(args))
filterOp = "AND"
}
if len(filter.Address) > 0 {
args = append(args, filter.Address)
fmt.Fprintf(&sql, " %v tx_sender = $%v", filterOp, len(args))
Expand Down
2 changes: 2 additions & 0 deletions dbtypes/other.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ type MevBlockFilter struct {
}

type DepositTxFilter struct {
MinIndex uint64
MaxIndex uint64
Address []byte
TargetAddress []byte
PublicKey []byte
Expand Down
118 changes: 117 additions & 1 deletion handlers/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ package handlers
import (
"encoding/hex"
"fmt"
"math"
"net/http"
"strconv"
"strings"
"time"

v1 "github.com/attestantio/go-eth2-client/api/v1"
"github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/ethereum/go-ethereum/common"
"github.com/gorilla/mux"
"github.com/sirupsen/logrus"

"github.com/ethpandaops/dora/db"
"github.com/ethpandaops/dora/dbtypes"
"github.com/ethpandaops/dora/indexer/beacon"
"github.com/ethpandaops/dora/services"
Expand Down Expand Up @@ -223,7 +226,7 @@ func buildValidatorPageData(validatorIndex uint64, tabView string) (*models.Vali
epoch := phase0.Epoch(epochIdx)
found := false

for validatorActivityIdx < len(validatorActivity) && chainState.EpochOfSlot(validatorActivity[validatorActivityIdx].VoteBlock.Slot) == epoch {
for validatorActivityIdx < len(validatorActivity) && chainState.EpochOfSlot(validatorActivity[validatorActivityIdx].VoteBlock.Slot-phase0.Slot(validatorActivity[validatorActivityIdx].VoteDelay)) == epoch {
found = true
vote := validatorActivity[validatorActivityIdx]

Expand Down Expand Up @@ -294,6 +297,119 @@ func buildValidatorPageData(validatorIndex uint64, tabView string) (*models.Vali
// first get recent included deposits
pageData.RecentDeposits = make([]*models.ValidatorPageDataDeposit, 0)

// helper to load tx details for included deposits
buildTxDetails := func(depositTx *dbtypes.DepositTx) *models.ValidatorPageDataDepositTxDetails {
txDetails := &models.ValidatorPageDataDepositTxDetails{
BlockNumber: depositTx.BlockNumber,
BlockHash: depositTx.BlockRoot,
BlockTime: depositTx.BlockTime,
TxOrigin: common.Address(depositTx.TxSender).Hex(),
TxTarget: common.Address(depositTx.TxTarget).Hex(),
TxHash: depositTx.TxHash,
}

return txDetails
}

depositSyncState := dbtypes.DepositIndexerState{}
db.GetExplorerState("indexer.depositstate", &depositSyncState)

depositsData, totalIncludedDeposits := services.GlobalBeaconService.GetIncludedDepositsByFilter(&dbtypes.DepositFilter{
PublicKey: validator.Validator.PublicKey[:],
}, 0, 100)

if totalIncludedDeposits > 10 {
pageData.AdditionalIncludedDepositCount = totalIncludedDeposits - 10
}

if len(depositsData) > 0 && depositsData[0].Index != nil {
initiatedFilter := &dbtypes.DepositTxFilter{
PublicKey: validator.Validator.PublicKey[:],
MinIndex: *depositsData[0].Index + 1,
}

initiatedDeposits, totalInitiatedDeposits, _ := db.GetDepositTxsFiltered(0, 10, depositSyncState.FinalBlock, initiatedFilter)
if totalInitiatedDeposits > 10 {
pageData.AdditionalInitiatedDepositCount = totalInitiatedDeposits - 10
}

for _, deposit := range initiatedDeposits {
txStatus := uint64(1)
if deposit.Orphaned {
txStatus = uint64(2)
}

pageData.RecentDeposits = append(pageData.RecentDeposits, &models.ValidatorPageDataDeposit{
Index: uint64(deposit.Index),
HasIndex: true,
Time: time.Unix(int64(deposit.BlockTime), 0),
Amount: deposit.Amount,
WithdrawalCreds: deposit.WithdrawalCredentials,
TxStatus: txStatus,
TxDetails: buildTxDetails(deposit),
})
}
}

minDepositIndex := uint64(math.MaxUint64)
maxDepositIndex := uint64(0)
recentDepositsMap := make(map[uint64]*models.ValidatorPageDataDeposit)

for _, deposit := range depositsData {
blockStatus := uint64(1)
if deposit.Orphaned {
blockStatus = uint64(2)
}

depositData := &models.ValidatorPageDataDeposit{
IsIncluded: true,
Time: chainState.SlotToTime(phase0.Slot(deposit.SlotNumber)),
Amount: deposit.Amount,
WithdrawalCreds: deposit.WithdrawalCredentials,
Status: blockStatus,
}

if deposit.Index != nil {
depositData.HasIndex = true
depositData.Index = *deposit.Index

if *deposit.Index < minDepositIndex {
minDepositIndex = *deposit.Index
}
if *deposit.Index > maxDepositIndex {
maxDepositIndex = *deposit.Index
}

recentDepositsMap[*deposit.Index] = depositData
}

pageData.RecentDeposits = append(pageData.RecentDeposits, depositData)
}

if minDepositIndex < math.MaxUint64 {
depositTxs, _, _ := db.GetDepositTxsFiltered(0, 10, depositSyncState.FinalBlock, &dbtypes.DepositTxFilter{
MinIndex: minDepositIndex,
MaxIndex: maxDepositIndex,
PublicKey: validator.Validator.PublicKey[:],
})

for _, depositTx := range depositTxs {
recentDeposit := recentDepositsMap[depositTx.Index]
if recentDeposit == nil {
continue
}

txStatus := uint64(1)
if depositTx.Orphaned {
txStatus = uint64(2)
}

recentDeposit.TxStatus = txStatus
recentDeposit.TxDetails = buildTxDetails(depositTx)
}
}

pageData.RecentDepositCount = uint64(len(pageData.RecentDeposits))
}

return pageData, 10 * time.Minute
Expand Down
2 changes: 1 addition & 1 deletion templates/validator/recentAttestations.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="card">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-nobr" id="recent-blocks">
<table class="table table-nobr" id="recent-attestations">
<thead>
<tr>
<th>Epoch</th>
Expand Down
65 changes: 52 additions & 13 deletions templates/validator/recentDeposits.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
{{ define "recentDeposits" }}
<div class="card block-card">
<div class="card">
<div class="table-responsive">
<table class="table table-nobr" id="recent-deposits">
<thead>
<tr>
<th>Index</th>
<th>Slot</th>
<th data-timecol="duration">Time</th>
<th>Amount</th>
<th>Withdrawal Cred</th>
<th>Transaction</th>
<th>Incl. Status</th>
</tr>
</thead>
<tbody>
{{ if gt .RecentDepositCount 0 }}
{{ range $i, $deposit := .RecentDeposits }}
<tr>
{{ if $deposit.Orphaned }}
{{ if not $deposit.HasIndex }}
<td data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Deposit index not found">?</td>
{{ else }}
<td>{{ $deposit.Index }}</td>
{{ end }}
{{ if not $deposit.IsIncluded }}
<td data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Deposit not included in the beacon chain yet">?</td>
{{ else if eq $deposit.Status 2 }}
<td><a href="/slot/0x{{ printf "%x" $deposit.SlotRoot }}">{{ formatAddCommas $deposit.Slot }}</a></td>
{{ else }}
<td><a href="/slot/{{ $deposit.Slot }}">{{ formatAddCommas $deposit.Slot }}</a></td>
Expand All @@ -24,31 +33,61 @@
<td>{{ formatFullEthFromGwei $deposit.Amount }}</td>
<td>
<span>
{{ formatWithdawalCredentials $deposit.Withdrawalcredentials }}
{{ formatWithdawalCredentials $deposit.WithdrawalCreds }}
</span>
<i class="fa fa-copy text-muted ml-2 p-1" role="button" data-bs-toggle="tooltip" title="Copy to clipboard" data-clipboard-text="0x{{ printf "%x" $deposit.Withdrawalcredentials }}"></i>
<i class="fa fa-copy text-muted ml-2 p-1" role="button" data-bs-toggle="tooltip" title="Copy to clipboard" data-clipboard-text="0x{{ printf "%x" $deposit.WithdrawalCreds }}"></i>
</td>
<td>
{{- if $deposit.TxDetails }}
<div class="d-flex">
<span class="flex-grow-1 text-truncate" style="max-width: 150px;">{{ ethTransactionLink $deposit.TxDetails.TxHash 0 }}</span>
<div>
<i class="fa fa-copy text-muted ml-2 p-1" role="button" data-bs-toggle="tooltip" title="Copy to clipboard" data-clipboard-text="0x{{ printf "%x" $deposit.TxDetails.TxHash }}"></i>
</div>
<div>
<i class="fa fa-info-circle text-muted ml-2 p-1 nojs-hide tx-details-btn" role="button" data-txdetails="{{ includeJSON $deposit.TxDetails true }}"></i>
</div>
</div>
{{- else }}
<span data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Corresponding consolidation transaction has not been indexed yet.">?</span>
{{- end }}
</td>


<td>
{{ if $deposit.Queued }}
<span class="badge rounded-pill text-bg-warning">Queued</span>
{{ else if $deposit.Orphaned }}
<span class="badge rounded-pill text-bg-info">Orphaned</span>
{{ else }}
<span class="badge rounded-pill text-bg-success">Included</span>
{{ if eq $deposit.TxStatus 1 }}
<span class="badge rounded-pill text-bg-success">Tx Included</span>
{{ else if eq $deposit.TxStatus 2 }}
<span class="badge rounded-pill text-bg-info">Tx Orphaned</span>
{{ end }}

{{ if eq $deposit.Status 1 }}
<span class="badge rounded-pill text-bg-success">Req. Included</span>
{{ else if eq $deposit.Status 2 }}
<span class="badge rounded-pill text-bg-info">Req. Orphaned</span>
{{ else if eq $deposit.Status 0 }}
<span class="badge rounded-pill text-bg-secondary">Req. Pending</span>
{{ end }}
</td>
</tr>
{{ end }}
<tr>
<td colspan="6" class="text-center">
<a class="text-white" href="/validators/included_deposits?f&f.pubkey=0x{{ printf "%x" .PublicKey }}">View more</a>
<td colspan="7" class="text-center">
{{ if gt .AdditionalInitiatedDepositCount 0 }}
<a class="text-white" href="/validators/initiated_deposits?f&f.pubkey=0x{{ printf "%x" .PublicKey }}">View {{ .AdditionalInitiatedDepositCount }} more initiated deposits</a>
{{ end }}
{{ if and (gt .AdditionalInitiatedDepositCount 0) (gt .AdditionalIncludedDepositCount 0) }}
<span> / </span>
{{ end }}
{{ if gt .AdditionalIncludedDepositCount 0 }}
<a class="text-white" href="/validators/included_deposits?f&f.pubkey=0x{{ printf "%x" .PublicKey }}">View {{ .AdditionalIncludedDepositCount }} more included deposits</a>
{{ end }}
</td>
</tr>
{{ else }}
<tr style="height: 430px;">
<td></td>
<td style="vertical-align: middle;" colspan="4">
<td style="vertical-align: middle;" colspan="7">
<div class="img-fluid mx-auto p-3 d-flex align-items-center" style="max-height: 400px; max-width: 400px; overflow: hidden;">
{{ template "timeline_svg" }}
</div>
Expand Down
2 changes: 1 addition & 1 deletion templates/validator/validator.html
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ <h1 class="h4 mb-1 mb-md-0"><i class="fas fa-table mx-2"></i> Validator {{ forma
{{ template "recentAttestations" . }}
{{ end }}
</div>
<div class="tab-pane fade{{ if eq .TabView "deposits" }} show active{{ end }}" id="recentDeposits" role="tabpanel" aria-labelledby="recentDeposits-tab" data-loaded="{{ if eq .TabView "deposits" }}true{{ else }}false{{ end }}"></div>
<div class="tab-pane fade{{ if eq .TabView "deposits" }} show active{{ end }}" id="recentDeposits" role="tabpanel" aria-labelledby="recentDeposits-tab" data-loaded="{{ if eq .TabView "deposits" }}true{{ else }}false{{ end }}">
{{ if eq .TabView "deposits" }}
{{ template "recentDeposits" . }}
{{ end }}
Expand Down
35 changes: 21 additions & 14 deletions types/models/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ type ValidatorPageData struct {

TabView string `json:"tab_view"`

RecentBlocks []*ValidatorPageDataBlock `json:"recent_blocks"`
RecentBlockCount uint64 `json:"recent_block_count"`
RecentAttestations []*ValidatorPageDataAttestation `json:"recent_attestations"`
RecentAttestationCount uint64 `json:"recent_attestation_count"`
RecentDeposits []*ValidatorPageDataDeposit `json:"recent_deposits"`
RecentDepositCount uint64 `json:"recent_deposit_count"`
RecentBlocks []*ValidatorPageDataBlock `json:"recent_blocks"`
RecentBlockCount uint64 `json:"recent_block_count"`
RecentAttestations []*ValidatorPageDataAttestation `json:"recent_attestations"`
RecentAttestationCount uint64 `json:"recent_attestation_count"`
RecentDeposits []*ValidatorPageDataDeposit `json:"recent_deposits"`
RecentDepositCount uint64 `json:"recent_deposit_count"`
AdditionalInitiatedDepositCount uint64 `json:"additional_initiated_deposit_count"`
AdditionalIncludedDepositCount uint64 `json:"additional_included_deposit_count"`
}

type ValidatorPageDataBlock struct {
Expand Down Expand Up @@ -66,19 +68,24 @@ type ValidatorPageDataAttestation struct {
}

type ValidatorPageDataDeposit struct {
SlotRoot string `json:"slot_root"`
Slot uint64 `json:"slot"`
Amount uint64 `json:"amount"`
Time time.Time `json:"time"`
Status uint64 `json:"status"`
TxDetails *ValidatorPageDataDepositTxDetails `json:"tx_details"`
IsIncluded bool `json:"is_included"`
HasIndex bool `json:"has_index"`
Index uint64 `json:"index"`
SlotRoot []byte `json:"slot_root"`
Slot uint64 `json:"slot"`
Time time.Time `json:"time"`
Amount uint64 `json:"amount"`
WithdrawalCreds []byte `json:"withdrawal_creds"`
Status uint64 `json:"status"`
TxStatus uint64 `json:"tx_status"`
TxDetails *ValidatorPageDataDepositTxDetails `json:"tx_details"`
}

type ValidatorPageDataDepositTxDetails struct {
BlockNumber uint64 `json:"block"`
BlockHash string `json:"block_hash"`
BlockHash []byte `json:"block_hash"`
BlockTime uint64 `json:"block_time"`
TxOrigin string `json:"tx_origin"`
TxTarget string `json:"tx_target"`
TxHash string `json:"tx_hash"`
TxHash []byte `json:"tx_hash"`
}

0 comments on commit 0f74f94

Please sign in to comment.