Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement get active validators #12

Merged
merged 7 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ MONGO_DB_NAME=
MONGO_DB_API_PORT=
API_PORT=
LOG_LEVEL=
BEACON_NODE_URL=
1 change: 1 addition & 0 deletions listener/cmd/listener/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func main() {
s := api.NewApi(
config.Port,
config.MongoDBURI,
config.BeaconNodeURL,
)

s.Start()
Expand Down
16 changes: 9 additions & 7 deletions listener/internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@ import (
)

type httpApi struct {
server *http.Server
port string
dbUri string
server *http.Server
port string
dbUri string
beaconNodeUrl string
}

// create a new api instance
func NewApi(port string, mongoDbUri string) *httpApi {
func NewApi(port string, mongoDbUri string, beaconNodeUrl string) *httpApi {
return &httpApi{
port: port,
dbUri: mongoDbUri,
port: port,
dbUri: mongoDbUri,
beaconNodeUrl: beaconNodeUrl,
}
}

Expand Down Expand Up @@ -47,7 +49,7 @@ func (s *httpApi) Start() {
// setup the http api
s.server = &http.Server{
Addr: ":" + s.port,
Handler: routes.SetupRouter(dbCollection),
Handler: routes.SetupRouter(dbCollection, s.beaconNodeUrl),
}

// start the api
Expand Down
4 changes: 2 additions & 2 deletions listener/internal/api/handlers/postNewSignature.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func validateAndInsertSignature(req types.SignatureRequestDecoded, dbCollection
// 1. Decode and validate
// 2. Get active validators
// 3. Validate signature and insert into MongoDB
func PostNewSignature(w http.ResponseWriter, r *http.Request, dbCollection *mongo.Collection) {
func PostNewSignature(w http.ResponseWriter, r *http.Request, dbCollection *mongo.Collection, beaconNodeUrl string) {
logger.Debug("Received new POST '/newSignature' request")

// Decode and validate incoming requests
Expand All @@ -117,7 +117,7 @@ func PostNewSignature(w http.ResponseWriter, r *http.Request, dbCollection *mong
}

// Get active validators
requestsWithActiveValidators, err := validation.GetActiveValidators(validRequests)
requestsWithActiveValidators, err := validation.GetActiveValidators(validRequests, beaconNodeUrl)
if err != nil {
respondError(w, http.StatusInternalServerError, "Failed to validate active validators")
return
Expand Down
4 changes: 2 additions & 2 deletions listener/internal/api/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import (
"go.mongodb.org/mongo-driver/mongo"
)

func SetupRouter(dbCollection *mongo.Collection) *mux.Router {
func SetupRouter(dbCollection *mongo.Collection, beaconNodeUrl string) *mux.Router {
r := mux.NewRouter()

// Define routes
r.HandleFunc("/", handlers.GetHealthCheck).Methods(http.MethodGet)
// closure function to inject dbCollection into the handler
r.HandleFunc("/newSignature", func(w http.ResponseWriter, r *http.Request) {
handlers.PostNewSignature(w, r, dbCollection)
handlers.PostNewSignature(w, r, dbCollection, beaconNodeUrl)
}).Methods(http.MethodPost)
r.HandleFunc("/signaturesByValidator", func(w http.ResponseWriter, r *http.Request) {
handlers.PostSignaturesByValidator(w, r, dbCollection)
Expand Down
67 changes: 60 additions & 7 deletions listener/internal/api/validation/GetActiveValidators.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,65 @@
package validation

import "github.com/dappnode/validator-monitoring/listener/internal/api/types"
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"

// ValidatePubkeysWithConsensusClient checks if the given pubkeys from the requests are from active validators
// or not by making SINGLE API call to the consensus client. It returns an array of the active validators pubkeys.
func GetActiveValidators(requestsDecoded []types.SignatureRequestDecoded) ([]types.SignatureRequestDecoded, error) {
requestsActiveValidators := requestsDecoded
// make api call: GET /eth/v1/beacon/states/{state_id}/validators?id=validator_pubkey1,validator_pubkey2,validator_pubkey3
"github.com/dappnode/validator-monitoring/listener/internal/api/types"
)

return requestsActiveValidators, nil
func GetActiveValidators(requestsDecoded []types.SignatureRequestDecoded, beaconNodeUrl string) ([]types.SignatureRequestDecoded, error) {
if len(requestsDecoded) == 0 {
return nil, fmt.Errorf("no validators to check")
}

// Prepare the request body
ids := make([]string, 0, len(requestsDecoded))
for _, req := range requestsDecoded {
ids = append(ids, req.DecodedPayload.Pubkey)
}
requestBody := struct {
Ids []string `json:"ids"`
Statuses []string `json:"statuses"`
}{
Ids: ids,
Statuses: []string{"active_ongoing"},
}

// Serialize the request body to JSON
jsonData, err := json.Marshal(requestBody)
if err != nil {
return nil, fmt.Errorf("error marshaling request body: %w", err)
}

// Configure HTTP client with timeout
client := &http.Client{Timeout: 10 * time.Second}
url := fmt.Sprintf("%s/eth/v1/beacon/states/head/validators", beaconNodeUrl)
resp, err := client.Post(url, "application/json", bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("error making API call to %s: %w", url, err)
}
defer resp.Body.Close()

// Check the HTTP response status before reading the body
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("API call to %s returned status %d", url, resp.StatusCode)
}

// Read and log the response body
responseData, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("error reading response data: %w", err)
}

// Assuming the server returns a list of active validators in the format you expect
var activeValidators []types.SignatureRequestDecoded
if err := json.Unmarshal(responseData, &activeValidators); err != nil {
return nil, fmt.Errorf("error unmarshaling response data: %w", err)
}

return activeValidators, nil
}
Empty file.
14 changes: 11 additions & 3 deletions listener/internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ type Config struct {
MongoDBURI string
// LogLevel is the level of logging
LogLevel string
// BeaconNodeURL is the URL of the beacon node
BeaconNodeURL string
}

func LoadConfig() (*Config, error) {
Expand All @@ -34,9 +36,15 @@ func LoadConfig() (*Config, error) {
logger.Fatal("API_PORT is not set")
}

beaconNodeURL := os.Getenv("BEACON_NODE_URL")
if beaconNodeURL == "" {
logger.Fatal("BEACON_NODE_URL is not set")
}

return &Config{
Port: apiPort,
MongoDBURI: mongoDBURI,
LogLevel: logLevel,
Port: apiPort,
MongoDBURI: mongoDBURI,
LogLevel: logLevel,
BeaconNodeURL: beaconNodeURL,
}, nil
}
Loading