Skip to content

Commit

Permalink
get active validartors for different networks
Browse files Browse the repository at this point in the history
  • Loading branch information
pablomendezroyo committed May 7, 2024
1 parent 37141f4 commit bf6dbde
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 66 deletions.
2 changes: 1 addition & 1 deletion listener/cmd/listener/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func main() {
s := api.NewApi(
config.Port,
config.MongoDBURI,
config.BeaconNodeURL,
config.BeaconNodeURLs,
)

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

type httpApi struct {
server *http.Server
port string
dbUri string
beaconNodeUrl string
server *http.Server
port string
dbUri string
beaconNodeUrls map[string]string
}

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

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

// start the api
Expand Down
10 changes: 3 additions & 7 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, beaconNodeUrl string) {
func PostNewSignature(w http.ResponseWriter, r *http.Request, dbCollection *mongo.Collection, beaconNodeUrls map[string]string) {
logger.Debug("Received new POST '/newSignature' request")

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

// Get active validators
requestsWithActiveValidators, err := validation.GetActiveValidators(validRequests, beaconNodeUrl)
if err != nil {
respondError(w, http.StatusInternalServerError, "Failed to validate active validators")
return
}
// Get active validators (not throws only takes active validators)
requestsWithActiveValidators := validation.GetActiveValidators(validRequests, beaconNodeUrls)
// Respond with an error if no active validators were found
if len(requestsWithActiveValidators) == 0 {
respondError(w, http.StatusInternalServerError, "No active validators found in request")
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, beaconNodeUrl string) *mux.Router {
func SetupRouter(dbCollection *mongo.Collection, beaconNodeUrls map[string]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, beaconNodeUrl)
handlers.PostNewSignature(w, r, dbCollection, beaconNodeUrls)
}).Methods(http.MethodPost)
r.HandleFunc("/signaturesByValidator", func(w http.ResponseWriter, r *http.Request) {
handlers.PostSignaturesByValidator(w, r, dbCollection)
Expand Down
103 changes: 62 additions & 41 deletions listener/internal/api/validation/GetActiveValidators.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,55 +11,76 @@ import (
"github.com/dappnode/validator-monitoring/listener/internal/api/types"
)

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

// 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"},
}
var activeValidators []types.SignatureRequestDecoded

// Serialize the request body to JSON
jsonData, err := json.Marshal(requestBody)
if err != nil {
return nil, fmt.Errorf("error marshaling request body: %w", err)
}
// iterate over the networks available in the beaconNodeUrls map
for network, url := range beaconNodeUrls {
// prepare request body, get the list of ids from the requestsDecoded for the current network
idss := make([]string, 0, len(requestsDecoded))
for _, req := range requestsDecoded {
if req.Network == network {
idss = append(idss, req.DecodedPayload.Pubkey)
}
}
// if there are no ids for the current network, log and skip it
if len(idss) == 0 {
fmt.Printf("no ids for network %s\n", network)
continue
}

// 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()
// serialize the request body to JSON
jsonData, err := json.Marshal(struct {
Ids []string `json:"ids"`
Statuses []string `json:"statuses"`
}{
Ids: idss,
Statuses: []string{"active_ongoing"},
})
if err != nil {
fmt.Printf("error marshaling request data: %v\n", err)
continue
}

// 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)
}
// configure HTTP client with timeout
client := &http.Client{Timeout: 10 * time.Second}
url := fmt.Sprintf("%s/eth/v1/beacon/states/head/validators", url)
resp, err := client.Post(url, "application/json", bytes.NewBuffer(jsonData))
if err != nil {
fmt.Printf("error making API call to %s: %v\n", url, err)
continue
}

// 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)
}
// check the HTTP response status before reading the body
if resp.StatusCode != http.StatusOK {
fmt.Printf("unexpected response status: %d\n", resp.StatusCode)
continue
}

// 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)
// read and log the response body
responseData, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Printf("error reading response data: %v\n", err)
continue
}

// assuming the server returns a list of active validators in the format expected
if err := json.Unmarshal(responseData, &activeValidators); err != nil {
fmt.Printf("error unmarshaling response data: %v\n", err)
continue
}

// append the active validators to the list
activeValidators = append(activeValidators, activeValidators...)

// close the response body
resp.Body.Close()
}

return activeValidators, nil
return activeValidators
}
9 changes: 9 additions & 0 deletions listener/internal/api/validation/GetActiveValidators_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package validation

import (
"testing"
)

func TestGetActiveValidators(t *testing.T) {

}
40 changes: 34 additions & 6 deletions listener/internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +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
// BeaconNodeURLs is the URLs of the beacon nodes for different networks
BeaconNodeURLs map[string]string
}

func LoadConfig() (*Config, error) {
Expand All @@ -41,10 +41,38 @@ func LoadConfig() (*Config, error) {
logger.Fatal("BEACON_NODE_URL is not set")
}

// beacon node urls per network

beaconMainnet := os.Getenv("BEACON_NODE_URL_MAINNET")
if beaconMainnet == "" {
logger.Fatal("BEACON_NODE_URL_MAINNET is not set")
}
beaconHolesky := os.Getenv("BEACON_NODE_URL_HOLESKY")
if beaconHolesky == "" {
logger.Fatal("BEACON_NODE_URL_HOLESKY is not set")
}

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

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

beaconNodeURLs := map[string]string{
"mainnet": beaconMainnet,
"holesky": beaconHolesky,
"gnosis": beaconGnosis,
"lukso": beaconLukso,
}

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

0 comments on commit bf6dbde

Please sign in to comment.