Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
0.9.2:
- add provider functions for consolidation and deposit requests

0.9.1:
- add commit hash to startup
- warn if blobs are no longer available in the beacon node for a block, but continue
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ import (
)

// ReleaseVersion is the release version for the code.
var ReleaseVersion = "0.9.1"
var ReleaseVersion = "0.9.2"

func main() {
os.Exit(main2())
Expand Down
64 changes: 64 additions & 0 deletions services/chaindb/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,3 +367,67 @@ type WithdrawalFilter struct {
// If nil then no filter is applied.
Canonical *bool
}

// ConsolidationRequestFilter defines a filter for fetching consolidation requests.
// Filter elements are ANDed together.
// Results are always returned in ascending (slot,index) order.
type ConsolidationRequestFilter struct {
// Limit is the maximum number of items to return.
Limit uint32

// Order is either OrderEarliest, in which case the earliest results
// that match the filter are returned, or OrderLatest, in which case the
// latest results that match the filter are returned.
// The default is OrderEarliest.
Order Order

// From is the earliest slot from which to fetch items.
// If nil then there is no earliest slot.
From *phase0.Slot

// To is the latest slot to which to fetch items.
// If nil then there is no latest slot.
To *phase0.Slot

// SourcePubkeys is the list of source validator public keys for which to obtain items.
// If nil then no filter is applied.
SourcePubkeys []phase0.BLSPubKey

// TargetPubkeys is the list of target validator public keys for which to obtain items.
// If nil then no filter is applied.
TargetPubkeys []phase0.BLSPubKey

// BlockRoots is the list of block roots for which to obtain items.
// If nil then no filter is applied.
BlockRoots []phase0.Root
}

// DepositRequestFilter defines a filter for fetching deposit requests.
// Filter elements are ANDed together.
// Results are always returned in ascending (slot,index) order.
type DepositRequestFilter struct {
// Limit is the maximum number of items to return.
Limit uint32

// Order is either OrderEarliest, in which case the earliest results
// that match the filter are returned, or OrderLatest, in which case the
// latest results that match the filter are returned.
// The default is OrderEarliest.
Order Order

// From is the earliest slot from which to fetch items.
// If nil then there is no earliest slot.
From *phase0.Slot

// To is the latest slot to which to fetch items.
// If nil then there is no latest slot.
To *phase0.Slot

// ValidatorPubkeys is the list of validator public keys for which to obtain items.
// If nil then no filter is applied.
ValidatorPubkeys []phase0.BLSPubKey

// BlockRoots is the list of block roots for which to obtain items.
// If nil then no filter is applied.
BlockRoots []phase0.Root
}
40 changes: 40 additions & 0 deletions services/chaindb/mock/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,46 @@ func (s *service) Withdrawals(_ context.Context, _ *chaindb.WithdrawalFilter) ([
return []*chaindb.Withdrawal{}, nil
}

// ConsolidationRequests provides consolidation requests according to the filter.
func (s *service) ConsolidationRequests(_ context.Context, _ *chaindb.ConsolidationRequestFilter) ([]*chaindb.ConsolidationRequest, error) {
return []*chaindb.ConsolidationRequest{}, nil
}

// SetConsolidationRequests sets multiple consolidation requests.
func (s *service) SetConsolidationRequests(_ context.Context, _ []*chaindb.ConsolidationRequest) error {
return nil
}

// SetConsolidationRequest sets a consolidation request.
func (s *service) SetConsolidationRequest(_ context.Context, _ *chaindb.ConsolidationRequest) error {
return nil
}

// DepositRequests provides deposit requests according to the filter.
func (s *service) DepositRequests(_ context.Context, _ *chaindb.DepositRequestFilter) ([]*chaindb.DepositRequest, error) {
return []*chaindb.DepositRequest{}, nil
}

// SetDepositRequests sets multiple deposit requests.
func (s *service) SetDepositRequests(_ context.Context, _ []*chaindb.DepositRequest) error {
return nil
}

// SetDepositRequest sets a deposit request.
func (s *service) SetDepositRequest(_ context.Context, _ *chaindb.DepositRequest) error {
return nil
}

// SetWithdrawalRequests sets multiple withdrawal requests.
func (s *service) SetWithdrawalRequests(_ context.Context, _ []*chaindb.WithdrawalRequest) error {
return nil
}

// SetWithdrawalRequest sets a withdrawal request.
func (s *service) SetWithdrawalRequest(_ context.Context, _ *chaindb.WithdrawalRequest) error {
return nil
}

// BeginTx begins a transaction.
func (s *service) BeginTx(_ context.Context) (context.Context, context.CancelFunc, error) {
return nil, nil, nil
Expand Down
163 changes: 163 additions & 0 deletions services/chaindb/postgresql/consolidationrequests.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
// Copyright © 2025 Weald Technology Trading.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package postgresql

import (
"context"
"fmt"
"sort"
"strings"

"github.com/pkg/errors"
"github.com/wealdtech/chaind/services/chaindb"
"go.opentelemetry.io/otel"
)

// ConsolidationRequests provides consolidation requests according to the filter.
func (s *Service) ConsolidationRequests(ctx context.Context, filter *chaindb.ConsolidationRequestFilter) ([]*chaindb.ConsolidationRequest, error) {
ctx, span := otel.Tracer("wealdtech.chaind.services.chaindb.postgresql").Start(ctx, "ConsolidationRequests")
defer span.End()

tx := s.tx(ctx)
if tx == nil {
ctx, err := s.BeginROTx(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to begin transaction")
}
defer s.CommitROTx(ctx)
tx = s.tx(ctx)
}

// Build the query.
queryBuilder := strings.Builder{}
queryVals := make([]any, 0)

queryBuilder.WriteString(`
SELECT f_block_root
,f_slot
,f_index
,f_source_address
,f_source_pubkey
,f_target_pubkey
FROM t_block_consolidation_requests`)

conditions := make([]string, 0)

if filter.From != nil {
queryVals = append(queryVals, *filter.From)
conditions = append(conditions, fmt.Sprintf("f_slot >= $%d", len(queryVals)))
}

if filter.To != nil {
queryVals = append(queryVals, *filter.To)
conditions = append(conditions, fmt.Sprintf("f_slot <= $%d", len(queryVals)))
}

if len(filter.SourcePubkeys) > 0 {
sourcePubkeysBytes := make([][]byte, len(filter.SourcePubkeys))
for i, pubkey := range filter.SourcePubkeys {
sourcePubkeysBytes[i] = pubkey[:]
}
queryVals = append(queryVals, sourcePubkeysBytes)
conditions = append(conditions, fmt.Sprintf("f_source_pubkey = ANY($%d)", len(queryVals)))
}

if len(filter.TargetPubkeys) > 0 {
targetPubkeysBytes := make([][]byte, len(filter.TargetPubkeys))
for i, pubkey := range filter.TargetPubkeys {
targetPubkeysBytes[i] = pubkey[:]
}
queryVals = append(queryVals, targetPubkeysBytes)
conditions = append(conditions, fmt.Sprintf("f_target_pubkey = ANY($%d)", len(queryVals)))
}

if len(filter.BlockRoots) > 0 {
queryVals = append(queryVals, filter.BlockRoots)
queryBuilder.WriteString(fmt.Sprintf("f_block_root = ANY($%d)", len(queryVals)))
}

if len(conditions) > 0 {
queryBuilder.WriteString("\nWHERE ")
queryBuilder.WriteString(strings.Join(conditions, " AND "))
}

switch filter.Order {
case chaindb.OrderEarliest:
queryBuilder.WriteString(`
ORDER BY f_slot, f_index`)
case chaindb.OrderLatest:
queryBuilder.WriteString(`
ORDER BY f_slot DESC, f_index DESC`)
default:
return nil, errors.New("no order specified")
}

if filter.Limit > 0 {
queryVals = append(queryVals, filter.Limit)
queryBuilder.WriteString(fmt.Sprintf(`
LIMIT $%d`, len(queryVals)))
}

if e := log.Trace(); e.Enabled() {
params := make([]string, len(queryVals))
for i := range queryVals {
params[i] = fmt.Sprintf("%v", queryVals[i])
}
e.Str("query", strings.ReplaceAll(queryBuilder.String(), "\n", " ")).Strs("params", params).Msg("SQL query")
}

rows, err := tx.Query(ctx,
queryBuilder.String(),
queryVals...,
)
if err != nil {
return nil, err
}
defer rows.Close()

requests := make([]*chaindb.ConsolidationRequest, 0)
for rows.Next() {
request := &chaindb.ConsolidationRequest{}
var blockRoot []byte
var sourceAddress []byte
var sourcePubkey []byte
var targetPubkey []byte
err := rows.Scan(
&blockRoot,
&request.InclusionSlot,
&request.InclusionIndex,
&sourceAddress,
&sourcePubkey,
&targetPubkey,
)
if err != nil {
return nil, errors.Wrap(err, "failed to scan row")
}
copy(request.InclusionBlockRoot[:], blockRoot)
copy(request.SourceAddress[:], sourceAddress)
copy(request.SourcePubkey[:], sourcePubkey)
copy(request.TargetPubkey[:], targetPubkey)
requests = append(requests, request)
}

// Always return order of slot then index.
sort.Slice(requests, func(i int, j int) bool {
if requests[i].InclusionSlot != requests[j].InclusionSlot {
return requests[i].InclusionSlot < requests[j].InclusionSlot
}
return requests[i].InclusionIndex < requests[j].InclusionIndex
})

return requests, nil
}
Loading