Skip to content

Commit ba87fc7

Browse files
committed
feat: initial Handshake indexer support
Signed-off-by: Aurora Gaffney <aurora@blinklabs.io>
1 parent 27a3f30 commit ba87fc7

File tree

4 files changed

+120
-13
lines changed

4 files changed

+120
-13
lines changed

internal/config/config.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,14 @@ type MetricsConfig struct {
5050
}
5151

5252
type IndexerConfig struct {
53-
Network string `yaml:"network" envconfig:"INDEXER_NETWORK"`
54-
NetworkMagic uint32 `yaml:"networkMagic" envconfig:"INDEXER_NETWORK_MAGIC"`
55-
Address string `yaml:"address" envconfig:"INDEXER_TCP_ADDRESS"`
56-
SocketPath string `yaml:"socketPath" envconfig:"INDEXER_SOCKET_PATH"`
57-
InterceptHash string `yaml:"interceptHash" envconfig:"INDEXER_INTERCEPT_HASH"`
58-
InterceptSlot uint64 `yaml:"interceptSlot" envconfig:"INDEXER_INTERCEPT_SLOT"`
59-
Verify bool `yaml:"verify" envconfig:"INDEXER_VERIFY"`
53+
Network string `yaml:"network" envconfig:"INDEXER_NETWORK"`
54+
NetworkMagic uint32 `yaml:"networkMagic" envconfig:"INDEXER_NETWORK_MAGIC"`
55+
Address string `yaml:"address" envconfig:"INDEXER_TCP_ADDRESS"`
56+
SocketPath string `yaml:"socketPath" envconfig:"INDEXER_SOCKET_PATH"`
57+
InterceptHash string `yaml:"interceptHash" envconfig:"INDEXER_INTERCEPT_HASH"`
58+
InterceptSlot uint64 `yaml:"interceptSlot" envconfig:"INDEXER_INTERCEPT_SLOT"`
59+
Verify bool `yaml:"verify" envconfig:"INDEXER_VERIFY"`
60+
HandshakeAddress string `yaml:"handshakeAddress" envconfig:"INDEXER_HANDSHAKE_ADDRESS"`
6061
}
6162

6263
type StateConfig struct {

internal/handshake/peer.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,8 @@ func (p *Peer) Sync(locator [][32]byte, syncFunc SyncFunc) error {
476476
p.errorCh <- err
477477
_ = p.Close()
478478
}
479+
// Close error channel to signify shutdown to consumer
480+
close(p.errorCh)
479481
}(locator)
480482
return nil
481483
}

internal/indexer/handshake.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright 2025 Blink Labs Software
2+
//
3+
// Use of this source code is governed by an MIT-style
4+
// license that can be found in the LICENSE file or at
5+
// https://opensource.org/licenses/MIT.
6+
7+
package indexer
8+
9+
import (
10+
"fmt"
11+
"log/slog"
12+
"time"
13+
14+
"github.com/blinklabs-io/cdnsd/internal/config"
15+
"github.com/blinklabs-io/cdnsd/internal/handshake"
16+
)
17+
18+
type handshakeState struct {
19+
peer *handshake.Peer
20+
peerAddress string
21+
peerBackoffDelay time.Duration
22+
blockHeight int
23+
}
24+
25+
func (i *Indexer) startHandshake() error {
26+
cfg := config.GetConfig()
27+
if cfg.Indexer.HandshakeAddress == "" {
28+
return nil
29+
}
30+
i.handshakeState.peerAddress = cfg.Indexer.HandshakeAddress
31+
if err := i.handshakeConnectPeer(); err != nil {
32+
return err
33+
}
34+
if err := i.handshakeState.peer.Sync(nil, i.handshakeHandleSync); err != nil {
35+
return err
36+
}
37+
return nil
38+
}
39+
40+
func (i *Indexer) handshakeConnectPeer() error {
41+
slog.Info("connecting to Handshake peer", "address", i.handshakeState.peerAddress)
42+
p, err := handshake.NewPeer(nil, handshake.NetworkMainnet)
43+
if err != nil {
44+
return err
45+
}
46+
i.handshakeState.peer = p
47+
if err := i.handshakeState.peer.Connect(i.handshakeState.peerAddress); err != nil {
48+
return err
49+
}
50+
// Async error handler
51+
go func() {
52+
err := <-i.handshakeState.peer.ErrorChan()
53+
if err != nil {
54+
slog.Error(
55+
"peer disconnected",
56+
"error",
57+
err,
58+
)
59+
}
60+
// Try reconnecting to peer until we are successful
61+
for {
62+
if err := i.handshakeConnectPeer(); err == nil {
63+
i.handshakeState.peerBackoffDelay = 0
64+
return
65+
}
66+
if i.handshakeState.peerBackoffDelay == 0 {
67+
// Set initial backoff delay
68+
i.handshakeState.peerBackoffDelay = 1 * time.Second
69+
} else {
70+
// Double backoff delay
71+
i.handshakeState.peerBackoffDelay *= 2
72+
}
73+
// Don't delay longer than 2m
74+
if i.handshakeState.peerBackoffDelay > 120*time.Second {
75+
i.handshakeState.peerBackoffDelay = 120
76+
}
77+
slog.Error(
78+
"connection to Handshake peer failed",
79+
"error",
80+
err,
81+
"delay",
82+
i.handshakeState.peerBackoffDelay.String(),
83+
)
84+
}
85+
}()
86+
return nil
87+
}
88+
89+
func (i *Indexer) handshakeHandleSync(block *handshake.Block) error {
90+
i.handshakeState.blockHeight++
91+
fmt.Printf("height = %d, hash = %x, prev_hash = %x\n", i.handshakeState.blockHeight, block.Hash(), block.Header.PrevBlock)
92+
return nil
93+
}

internal/indexer/indexer.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,13 @@ type Domain struct {
5555
}
5656

5757
type Indexer struct {
58-
pipeline *pipeline.Pipeline
59-
domains map[string]Domain
60-
tipReached bool
61-
syncLogTimer *time.Timer
62-
syncStatus input_chainsync.ChainSyncStatus
63-
watched []watchedAddr
58+
pipeline *pipeline.Pipeline
59+
domains map[string]Domain
60+
tipReached bool
61+
syncLogTimer *time.Timer
62+
syncStatus input_chainsync.ChainSyncStatus
63+
watched []watchedAddr
64+
handshakeState handshakeState
6465
}
6566

6667
type watchedAddr struct {
@@ -76,6 +77,16 @@ var globalIndexer = &Indexer{
7677
}
7778

7879
func (i *Indexer) Start() error {
80+
if err := i.startCardano(); err != nil {
81+
return err
82+
}
83+
if err := i.startHandshake(); err != nil {
84+
return err
85+
}
86+
return nil
87+
}
88+
89+
func (i *Indexer) startCardano() error {
7990
// Build watched addresses from enabled profiles
8091
cfg := config.GetConfig()
8192
for _, profile := range config.GetProfiles() {

0 commit comments

Comments
 (0)