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
8 changes: 3 additions & 5 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,15 @@ import (
"time"

"github.com/dappnode/validator-tracker/internal/adapters/beacon"
"github.com/dappnode/validator-tracker/internal/adapters/brain"
"github.com/dappnode/validator-tracker/internal/adapters/dappmanager"
"github.com/dappnode/validator-tracker/internal/adapters/notifier"
"github.com/dappnode/validator-tracker/internal/adapters/web3signer"
"github.com/dappnode/validator-tracker/internal/application/domain"
"github.com/dappnode/validator-tracker/internal/application/services"
"github.com/dappnode/validator-tracker/internal/config"
"github.com/dappnode/validator-tracker/internal/logger"
)

//TODO: Implement dev mode with commands example

func main() {
// Load config
cfg := config.LoadConfig()
Expand All @@ -35,7 +33,7 @@ func main() {
cfg.Network,
cfg.SignerDnpName,
)
web3Signer := web3signer.NewWeb3SignerAdapter(cfg.Web3SignerEndpoint)
brain := brain.NewBrainAdapter(cfg.BrainUrl)
// TODO: do not err
beacon, err := beacon.NewBeaconAdapter(cfg.BeaconEndpoint)
if err != nil {
Expand All @@ -50,7 +48,7 @@ func main() {
// Start the duties checker service in a goroutine
dutiesChecker := &services.DutiesChecker{
Beacon: beacon,
Signer: web3Signer,
Brain: brain,
Notifier: notifier,
Dappmanager: dappmanager,
PollInterval: 1 * time.Minute,
Expand Down
82 changes: 82 additions & 0 deletions internal/adapters/brain/brain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package brain

import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"

"github.com/dappnode/validator-tracker/internal/application/ports"
)

// This adapter is required to be used due to the web3signer blocklisting any host requesting its API that is not whitelisted.
// See https://github.com/dappnode/DAppNodePackage-web3signer-generic/blob/e50e36e6fe213f274cceefc2a089552fa6042be4/services/web3signer/entrypoint.sh#L41C28-L41C42

type BrainAdapter struct {
BaseURL string
client *http.Client
}

type brainValidatorsResponse map[string][]string

func NewBrainAdapter(baseURL string) ports.BrainAdapter {
// Always append :5000 if not present
u, err := url.Parse(baseURL)
if err == nil && u.Port() == "" {
if u.Scheme == "" {
baseURL = fmt.Sprintf("%s:5000", baseURL)
} else {
u.Host = fmt.Sprintf("%s:5000", u.Host)
baseURL = u.String()
}
} else if err != nil && !strings.HasSuffix(baseURL, ":5000") {
baseURL = fmt.Sprintf("%s:5000", baseURL)
}
return &BrainAdapter{
BaseURL: baseURL,
client: &http.Client{Timeout: 3 * time.Second},
}
}

// GetValidatorPubkeys queries /api/v0/brain/validators?format=pubkey and merges all arrays in the response
func (b *BrainAdapter) GetValidatorPubkeys() ([]string, error) {
endpoint := fmt.Sprintf("%s/api/v0/brain/validators", b.BaseURL)

u, err := url.Parse(endpoint)
if err != nil {
return nil, fmt.Errorf("invalid brain endpoint: %w", err)
}
q := u.Query()
q.Set("format", "pubkey")
u.RawQuery = q.Encode()

req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
return nil, fmt.Errorf("creating brain request: %w", err)
}

resp, err := b.client.Do(req)
if err != nil {
return nil, fmt.Errorf("error sending brain request: %w", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("unexpected brain status %d: %s", resp.StatusCode, string(body))
}

var result brainValidatorsResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("error decoding brain response: %w", err)
}

var pubkeys []string
for _, arr := range result {
pubkeys = append(pubkeys, arr...)
}
return pubkeys, nil
}
59 changes: 0 additions & 59 deletions internal/adapters/web3signer/web3signer.go

This file was deleted.

6 changes: 6 additions & 0 deletions internal/application/ports/brain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package ports

// BrainAdapter exposes the same method as Web3SignerAdapter for validator pubkeys
type BrainAdapter interface {
GetValidatorPubkeys() ([]string, error)
}
5 changes: 0 additions & 5 deletions internal/application/ports/web3signer.go

This file was deleted.

6 changes: 3 additions & 3 deletions internal/application/services/dutieschecker_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

type DutiesChecker struct {
Beacon ports.BeaconChainAdapter
Signer ports.Web3SignerAdapter
Brain ports.BrainAdapter
Notifier ports.NotifierPort
Dappmanager ports.DappManagerPort

Expand Down Expand Up @@ -59,9 +59,9 @@ func (a *DutiesChecker) performChecks(ctx context.Context, justifiedEpoch domain
logger.Warn("Error fetching notifications enabled, notification will not be sent: %v", err)
}

pubkeys, err := a.Signer.GetValidatorPubkeys()
pubkeys, err := a.Brain.GetValidatorPubkeys()
if err != nil {
logger.Error("Error fetching pubkeys from web3signer: %v", err)
logger.Error("Error fetching pubkeys from brain: %v", err)
return err
}

Expand Down
4 changes: 2 additions & 2 deletions internal/config/config_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func LoadConfig() Config {
web3SignerEndpoint := fmt.Sprintf("http://web3signer.%s.dncore.dappnode:9000", network)
dappmanagerEndpoint := "http://dappmanager.dappnode"
notifierEndpoint := "http://notifier.dappnode:8080"
brainEndpoint := fmt.Sprintf("http://brain.web3signer-%s.dappnode:5000", network)
brainEndpoint := fmt.Sprintf("http://brain.web3signer-%s.dappnode", network)

// Allow override via environment variables
if envBeacon := os.Getenv("BEACON_ENDPOINT"); envBeacon != "" {
Expand Down Expand Up @@ -58,7 +58,7 @@ func LoadConfig() Config {
var dnpName string
if network == "mainnet" {
dnpName = "web3signer.dnp.dappnode.eth"
brainEndpoint = "http://brain.web3signer.dnp.dappnode.eth:8080"
brainEndpoint = "http://brain.web3signer.dappnode"
} else {
dnpName = fmt.Sprintf("web3signer-%s.dnp.dappnode.eth", network)
}
Expand Down