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
32 changes: 32 additions & 0 deletions tools/points-service/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func (p *PointsAPI) StartAPIServer(ctx context.Context, addr string) error {

r.HandleFunc("/admin/add_manual_entry", p.AddManualPointsEntry).Methods("POST")
r.HandleFunc("/admin/add_manual_opt_out", p.AddManualOptOut).Methods("POST")
r.HandleFunc("/admin/update_addr", p.UpdateAddrForManualValRecord).Methods("PUT")

srv := &http.Server{
Addr: addr,
Expand Down Expand Up @@ -144,6 +145,37 @@ func (p *PointsAPI) AddManualOptOut(w http.ResponseWriter, r *http.Request) {
writeJSON(w, resp, http.StatusOK)
}

func (p *PointsAPI) UpdateAddrForManualValRecord(w http.ResponseWriter, r *http.Request) {
if err := p.checkAuth(r.Header.Get("Authorization")); err != nil {
http.Error(w, err.Error(), http.StatusUnauthorized)
return
}

var req struct {
Pubkey string `json:"pubkey"`
OldAddr string `json:"old_addr"`
NewAddr string `json:"new_addr"`
}

if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}

if req.Pubkey == "" || req.OldAddr == "" || req.NewAddr == "" {
http.Error(w, "Missing or invalid required fields", http.StatusBadRequest)
return
}

if err := updateAddrForManualValRecord(p.db, p.logger, req.Pubkey, req.OldAddr, req.NewAddr); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

resp := map[string]string{"status": "success"}
writeJSON(w, resp, http.StatusOK)
}

func (p *PointsAPI) HealthCheck(w http.ResponseWriter, r *http.Request) {
if !p.ps.IsPointsRoutineRunning() {
http.Error(w, "Points routine not running", http.StatusServiceUnavailable)
Expand Down
46 changes: 45 additions & 1 deletion tools/points-service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,12 @@ func insertManualValRecord(db *sql.DB,
return nil
}

func insertOptOut(db *sql.DB, logger *slog.Logger, pubkey, adder, eventType string, outBlock uint64) {
func insertOptOut(
db *sql.DB,
logger *slog.Logger,
pubkey, adder, eventType string,
outBlock uint64,
) {

_, err := db.Exec(`
UPDATE validator_records
Expand Down Expand Up @@ -543,6 +548,45 @@ func insertManualOptOut(db *sql.DB, logger *slog.Logger, pubkey, adder string, o
return nil
}

func updateAddrForManualValRecord(
db *sql.DB,
logger *slog.Logger,
pubkey string,
oldAddr string,
newAddr string,
) error {
var count int
err := db.QueryRow(`
SELECT COUNT(*)
FROM validator_records
WHERE pubkey = ? AND adder = ? AND registry_type IS NULL AND event_type IS NULL
`, pubkey, oldAddr).Scan(&count)
if err != nil {
return fmt.Errorf("failed to query validator_records: %w", err)
}
if count == 0 {
return fmt.Errorf("no manual validator record found for pubkey %s with addr %s", pubkey, oldAddr)
}

res, err := db.Exec(`
UPDATE validator_records
SET adder = ?
WHERE pubkey = ? AND adder = ? AND registry_type IS NULL AND event_type IS NULL
`, newAddr, pubkey, oldAddr)
if err != nil {
return fmt.Errorf("failed to update adder for manual val record: %w", err)
}

rows, _ := res.RowsAffected()
logger.Info("updated adder for manual validator record",
"pubkey", pubkey,
"old_addr", oldAddr,
"new_adder", newAddr,
"rows_affected", rows)

return nil
}

func getMsgSenderFromTxnHash(ethClient *ethclient.Client, txHash common.Hash) (common.Address, error) {
tx, _, err := ethClient.TransactionByHash(context.Background(), txHash)
if err != nil {
Expand Down
72 changes: 70 additions & 2 deletions tools/points-service/points_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,13 @@ func TestManualPointsEntry(t *testing.T) {
}
logger := slog.New(slog.NewTextHandler(io.Discard, nil))

insertOptIn(db, logger, "0x123", "0x456", "vanilla", "staked", 100)
vanillaStakedPubkey := "0x123"
vanillaStakedAddr := "0x456"
insertOptIn(db, logger, vanillaStakedPubkey, vanillaStakedAddr, "vanilla", "staked", 100)

if err := insertManualValRecord(db, "0x12345", "0x45678", 90); err != nil {
manuallyInsertedPubkey := "0x12345"
manuallyInsertedAddr := "0x45678"
if err := insertManualValRecord(db, manuallyInsertedPubkey, manuallyInsertedAddr, 90); err != nil {
t.Fatalf("failed to insert manual val record: %v", err)
}

Expand Down Expand Up @@ -181,4 +185,68 @@ func TestManualPointsEntry(t *testing.T) {
if optedOutBlockAfter2.String != "4001" {
t.Errorf("expected opted_out_block to be 4001, got %s", optedOutBlockAfter2.String)
}

newAddr := "0x2222222277777777"

err = updateAddrForManualValRecord(db, logger, vanillaStakedPubkey, vanillaStakedAddr, newAddr)
if err == nil {
t.Fatalf("expected error for updating addr of non-manually inserted record")
}

wrongOldAddr := "0x3333333377777777"
err = updateAddrForManualValRecord(db, logger, manuallyInsertedPubkey, wrongOldAddr, newAddr)
if err == nil {
t.Fatalf("expected error for updating addr of manually inserted record with wrong old addr")
}

wrongPubkey := "0xpkpkpk"
err = updateAddrForManualValRecord(db, logger, wrongPubkey, manuallyInsertedAddr, newAddr)
if err == nil {
t.Fatalf("expected error for updating addr of manually inserted record with wrong pubkey")
}

err = updateAddrForManualValRecord(db, logger, manuallyInsertedPubkey, manuallyInsertedAddr, newAddr)
if err != nil {
t.Fatalf("expected no error for updating addr of manually inserted record, got %v", err)
}

var countAfterUpdate int
err = db.QueryRow("SELECT COUNT(*) FROM validator_records").Scan(&countAfterUpdate)
if err != nil {
t.Fatalf("failed to query count: %v", err)
}
if countAfterUpdate != 2 {
t.Errorf("expected 2 records, got %d", countAfterUpdate)
}

var addrAfterUpdate sql.NullString
err = db.QueryRow("SELECT adder FROM validator_records WHERE pubkey = '0x12345'").Scan(&addrAfterUpdate)
if err != nil {
t.Fatalf("failed to query adder: %v", err)
}
if addrAfterUpdate.String != newAddr {
t.Errorf("expected adder to be %s, got %s", newAddr, addrAfterUpdate.String)
}

// Confirm we can change it a second time
newAddrAgain := "0xagain"

err = updateAddrForManualValRecord(db, logger, manuallyInsertedPubkey, manuallyInsertedAddr, newAddrAgain)
if err == nil {
t.Fatalf("expected error for updating addr of manually inserted record with same old addr as last time")
}

err = updateAddrForManualValRecord(db, logger, manuallyInsertedPubkey, newAddr, newAddrAgain)
if err != nil {
t.Fatalf("expected no error for updating addr of manually inserted record, got %v", err)
}

var addrAfterSecondUpdate sql.NullString
err = db.QueryRow("SELECT adder FROM validator_records WHERE pubkey = '0x12345'").Scan(&addrAfterSecondUpdate)
if err != nil {
t.Fatalf("failed to query adder: %v", err)
}
if addrAfterSecondUpdate.String != newAddrAgain {
t.Errorf("expected adder to be %s, got %s", newAddrAgain, addrAfterSecondUpdate.String)
}
}
Loading