@@ -12,6 +12,8 @@ import (
1212 "time"
1313
1414 "github.com/attestantio/go-eth2-client/spec/phase0"
15+ "github.com/doug-martin/goqu/v9"
16+ _ "github.com/doug-martin/goqu/v9/dialect/postgres"
1517 "github.com/ethereum/go-ethereum/accounts/abi"
1618 "github.com/ethereum/go-ethereum/accounts/abi/bind"
1719 "github.com/ethereum/go-ethereum/common"
@@ -26,11 +28,13 @@ import (
2628 "github.com/gobitfly/beaconchain/pkg/commons/contracts/deposit_contract"
2729 "github.com/gobitfly/beaconchain/pkg/commons/db"
2830 "github.com/gobitfly/beaconchain/pkg/commons/log"
31+ "github.com/gobitfly/beaconchain/pkg/commons/metrics"
2932 "github.com/gobitfly/beaconchain/pkg/commons/rpc"
3033 "github.com/gobitfly/beaconchain/pkg/commons/services"
3134 "github.com/gobitfly/beaconchain/pkg/commons/types"
3235 "github.com/gobitfly/beaconchain/pkg/commons/utils"
3336 constypes "github.com/gobitfly/beaconchain/pkg/consapi/types"
37+ edb "github.com/gobitfly/beaconchain/pkg/exporter/db"
3438 "github.com/gobitfly/beaconchain/pkg/monitoring/constants"
3539)
3640
@@ -50,6 +54,7 @@ type executionDepositsExporter struct {
5054 LastExportedBlock uint64
5155 LastExportedFinalizedBlock uint64
5256 LastExportedFinalizedBlockRedisKey string
57+ LastLookupTableRefresh time.Time
5358 CurrentHeadBlock atomic.Uint64
5459 Signer gethtypes.Signer
5560 DepositMethod abi.Method
@@ -278,14 +283,32 @@ func (d *executionDepositsExporter) export() (err error) {
278283 }
279284
280285 start := time .Now ()
281- // update cached view
282- err = d .updateCachedView ()
286+ var g2 errgroup.Group
287+ g2 .Go (func () error {
288+ // update cached view
289+ err := d .updateCachedView ()
290+ if err != nil {
291+ return err
292+ }
293+ log .Debugf ("updating cached deposits view took %v" , time .Since (start ))
294+ return nil
295+ })
296+ g2 .Go (func () error {
297+ if d .LastLookupTableRefresh .Before (time .Now ().Add (- time .Minute * 5 )) {
298+ err := d .upkeepLookupTable ()
299+ if err != nil {
300+ return err
301+ }
302+ d .LastLookupTableRefresh = time .Now ()
303+ log .Debugf ("updating lookup table took %v" , time .Since (start ))
304+ }
305+ return nil
306+ })
307+ err = g2 .Wait ()
283308 if err != nil {
284309 return err
285310 }
286311
287- log .Debugf ("updating cached deposits view took %v" , time .Since (start ))
288-
289312 return nil
290313}
291314
@@ -694,3 +717,80 @@ func (d *executionDepositsExporter) updateCachedView() error {
694717 []string {"dashboard_id" , "amount" })
695718 return err
696719}
720+
721+ func (d * executionDepositsExporter ) upkeepLookupTable () error {
722+ // metrics: overall invocation
723+ metrics .Tasks .WithLabelValues ("execution_deposits_exporter_upkeep_lookup" ).Inc ()
724+ startTotal := time .Now ()
725+ defer func () { metrics .TaskDuration .WithLabelValues ("execution_deposits_exporter_upkeep_lookup.total" ).Observe (time .Since (startTotal ).Seconds ()) }()
726+
727+ // Build external ClickHouse table with required schema
728+ tbl , err := edb .NewLookupExternalTable ()
729+ if err != nil {
730+ metrics .Errors .WithLabelValues ("execution_deposits_exporter_upkeep_lookup" ).Inc ()
731+ return fmt .Errorf ("error creating external table: %w" , err )
732+ }
733+
734+ // Fetch distinct deposit address -> validator index mappings from Postgres (built with goqu)
735+ startPg := time .Now ()
736+ ds := goqu .Dialect ("postgres" ).
737+ From (goqu .T ("eth1_deposits" ).As ("ed" )).
738+ Select (
739+ goqu .Func ("ENCODE" , goqu .T ("ed" ).Col ("from_address" ), "hex" ).As ("from_hex" ),
740+ goqu .T ("v" ).Col ("validatorindex" ).As ("validator_index" ),
741+ ).
742+ Distinct ().
743+ InnerJoin (
744+ goqu .T ("validators" ).As ("v" ),
745+ goqu .On (goqu .T ("v" ).Col ("pubkey" ).Eq (goqu .T ("ed" ).Col ("publickey" ))),
746+ ).
747+ Where (
748+ goqu .T ("ed" ).Col ("from_address" ).IsNotNull (),
749+ )
750+ sqlStr , args , err := ds .Prepared (true ).ToSQL ()
751+ if err != nil {
752+ metrics .Errors .WithLabelValues ("execution_deposits_exporter_upkeep_lookup" ).Inc ()
753+ return fmt .Errorf ("error building deposit address mappings query: %w" , err )
754+ }
755+ rows , err := db .ReaderDb .Query (sqlStr , args ... )
756+ metrics .TaskDuration .WithLabelValues ("execution_deposits_exporter_upkeep_lookup.pg_query" ).Observe (time .Since (startPg ).Seconds ())
757+ if err != nil {
758+ metrics .Errors .WithLabelValues ("execution_deposits_exporter_upkeep_lookup" ).Inc ()
759+ return fmt .Errorf ("error querying deposit address mappings: %w" , err )
760+ }
761+ defer rows .Close ()
762+
763+ startAppend := time .Now ()
764+ var rowsAppended int64
765+ for rows .Next () {
766+ var fromHex string
767+ var validatorIndex int64
768+ if err := rows .Scan (& fromHex , & validatorIndex ); err != nil {
769+ metrics .Errors .WithLabelValues ("execution_deposits_exporter_upkeep_lookup" ).Inc ()
770+ return fmt .Errorf ("error scanning deposit address mapping row: %w" , err )
771+ }
772+ // Prefix 0x for selector value consistency
773+ selector := "0x" + fromHex
774+ if err := tbl .Append (string (edb .DepositAddressSelector ), selector , uint64 (validatorIndex )); err != nil {
775+ metrics .Errors .WithLabelValues ("execution_deposits_exporter_upkeep_lookup" ).Inc ()
776+ return fmt .Errorf ("error appending row to external table: %w" , err )
777+ }
778+ rowsAppended ++
779+ }
780+ if err := rows .Err (); err != nil {
781+ metrics .Errors .WithLabelValues ("execution_deposits_exporter_upkeep_lookup" ).Inc ()
782+ return fmt .Errorf ("row iteration error: %w" , err )
783+ }
784+ metrics .TaskDuration .WithLabelValues ("execution_deposits_exporter_upkeep_lookup.append_rows" ).Observe (time .Since (startAppend ).Seconds ())
785+ metrics .Counter .WithLabelValues ("execution_deposits_exporter_upkeep_lookup.rows_appended" ).Add (float64 (rowsAppended ))
786+
787+ // Update the ClickHouse lookup table
788+ startCH := time .Now ()
789+ ctx := context .Background ()
790+ if err := edb .UpdateLookupTable (ctx , edb .DepositAddressSelector , tbl ); err != nil {
791+ metrics .Errors .WithLabelValues ("execution_deposits_exporter_upkeep_lookup" ).Inc ()
792+ return fmt .Errorf ("error updating deposit address lookup table: %w" , err )
793+ }
794+ metrics .TaskDuration .WithLabelValues ("execution_deposits_exporter_upkeep_lookup.ch_update" ).Observe (time .Since (startCH ).Seconds ())
795+ return nil
796+ }
0 commit comments