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

Bids 2872/ratelimits #2827

Merged
merged 42 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
dcf8b53
(BIDS-2872) wip
guybrush Jan 17, 2024
ae8b4e0
(BIDS-2872) wip
guybrush Jan 18, 2024
6ccd2ee
(BIDS-2872) wip
guybrush Jan 22, 2024
66ced50
(BIDS-2872) wip
guybrush Jan 22, 2024
f08aa09
(BIDS-2872) wip
guybrush Jan 23, 2024
a686b87
(BIDS-2872) wip
guybrush Jan 24, 2024
044defb
(BIDS-2872) wip
guybrush Jan 25, 2024
b47dbf0
(BIDS-2872) wip
guybrush Jan 25, 2024
4ee41f5
(BIDS-2872) wip
guybrush Jan 30, 2024
8f2cbcb
(BIDS-2872) wip
guybrush Feb 8, 2024
49de9a7
(BIDS-2872) wip
guybrush Feb 9, 2024
4b52d57
(BIDS-2872) wip
guybrush Feb 12, 2024
c6cfbef
(BIDS-2872) wip
guybrush Feb 12, 2024
15eb4be
(BIDS-2872) wip
guybrush Feb 13, 2024
fb5d679
(BIDS-2872) wip
guybrush Feb 13, 2024
cde7119
(BIDS-2872) wip
guybrush Feb 13, 2024
c2c313e
(BIDS-2872) wip
guybrush Feb 13, 2024
da5307f
(BIDS-2872) wip
guybrush Feb 13, 2024
4119e07
(BIDS-2872) wip
guybrush Feb 13, 2024
1581cce
(BIDS-2872) wip
guybrush Feb 14, 2024
495042a
(BIDS-2872) wip
guybrush Feb 14, 2024
3c657cf
(BIDS-2872) wip
guybrush Feb 14, 2024
41ce3b4
(BIDS-2872) wip
guybrush Feb 14, 2024
2acfcca
(BIDS-2872) wip
guybrush Feb 14, 2024
d27e685
(BIDS-2872) wip
guybrush Feb 14, 2024
fc3daeb
(BIDS-2872) wip
guybrush Feb 15, 2024
3bba31e
(BIDS-2872) wip
guybrush Feb 15, 2024
9dd2062
(BIDS-2872) wip
guybrush Feb 15, 2024
fe08b2f
(BIDS-2872) wip
guybrush Feb 15, 2024
f11aaa5
(BIDS-2872) wip
guybrush Feb 15, 2024
7774562
(BIDS-2872) wip
guybrush Feb 15, 2024
ca4a629
(BIDS-2872) wip
guybrush Feb 15, 2024
8b34b60
(BIDS-2872) wip
guybrush Feb 15, 2024
5f76f30
(BIDS-2872) wip
guybrush Feb 15, 2024
e7fafcd
(BIDS-2872) wip
guybrush Feb 15, 2024
59d5c59
(BIDS-2872) wip
guybrush Feb 15, 2024
f79524c
(BIDS-2872) fix ratelimit.DBGetUserApiRateLimit
guybrush Feb 16, 2024
ad5e31a
(BIDS-2872) improve sql-migration
guybrush Feb 19, 2024
d0c6691
(BIDS-2872) improve logging
guybrush Feb 19, 2024
97e06f8
(BIDS-2872) fix updateStats
guybrush Feb 21, 2024
e26215b
(BIDS-2872) use api_statistics.endpoint instead of api_statistics.cal…
guybrush Feb 21, 2024
ee9cf42
(BIDS-2872) fix updateStats
guybrush Feb 21, 2024
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
4 changes: 4 additions & 0 deletions cmd/explorer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"eth2-exporter/handlers"
"eth2-exporter/metrics"
"eth2-exporter/price"
"eth2-exporter/ratelimit"
"eth2-exporter/rpc"
"eth2-exporter/services"
"eth2-exporter/static"
Expand Down Expand Up @@ -606,6 +607,9 @@ func main() {
router.Use(metrics.HttpMiddleware)
}

ratelimit.Init()
router.Use(ratelimit.HttpMiddleware)

n := negroni.New(negroni.NewRecovery())
n.Use(gzip.Gzip(gzip.DefaultCompression))

Expand Down
5 changes: 4 additions & 1 deletion cmd/misc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"eth2-exporter/cmd/misc/commands"
"eth2-exporter/db"
"eth2-exporter/exporter"
"eth2-exporter/ratelimit"
"eth2-exporter/rpc"
"eth2-exporter/services"
"eth2-exporter/types"
Expand Down Expand Up @@ -66,7 +67,7 @@ func main() {
statsPartitionCommand := commands.StatsMigratorCommand{}

configPath := flag.String("config", "config/default.config.yml", "Path to the config file")
flag.StringVar(&opts.Command, "command", "", "command to run, available: updateAPIKey, applyDbSchema, initBigtableSchema, epoch-export, debug-rewards, debug-blocks, clear-bigtable, index-old-eth1-blocks, update-aggregation-bits, historic-prices-export, index-missing-blocks, export-epoch-missed-slots, migrate-last-attestation-slot-bigtable, export-genesis-validators, update-block-finalization-sequentially, nameValidatorsByRanges, export-stats-totals, export-sync-committee-periods, export-sync-committee-validator-stats, partition-validator-stats, migrate-app-purchases")
flag.StringVar(&opts.Command, "command", "", "command to run, available: updateAPIKey, applyDbSchema, initBigtableSchema, epoch-export, debug-rewards, debug-blocks, clear-bigtable, index-old-eth1-blocks, update-aggregation-bits, historic-prices-export, index-missing-blocks, export-epoch-missed-slots, migrate-last-attestation-slot-bigtable, export-genesis-validators, update-block-finalization-sequentially, nameValidatorsByRanges, export-stats-totals, export-sync-committee-periods, export-sync-committee-validator-stats, partition-validator-stats, migrate-app-purchases, update-ratelimits")
flag.Uint64Var(&opts.StartEpoch, "start-epoch", 0, "start epoch")
flag.Uint64Var(&opts.EndEpoch, "end-epoch", 0, "end epoch")
flag.Uint64Var(&opts.User, "user", 0, "user id")
Expand Down Expand Up @@ -391,6 +392,8 @@ func main() {
err = fixEns(erigonClient)
case "fix-ens-addresses":
err = fixEnsAddresses(erigonClient)
case "update-ratelimits":
ratelimit.DBUpdater()
default:
utils.LogFatal(nil, fmt.Sprintf("unknown command %s", opts.Command), 0)
}
Expand Down
23 changes: 23 additions & 0 deletions db/migrations/20240125110000_add_apps_subs_view.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-- +goose Up
-- +goose StatementBegin
SELECT 'up SQL query - add view app_subs_view';
CREATE OR REPLACE VIEW app_subs_view AS
SELECT users_app_subscriptions.id,
users_app_subscriptions.user_id,
users_app_subscriptions.product_id,
users_app_subscriptions.created_at,
users_app_subscriptions.updated_at,
users_app_subscriptions.validate_remotely,
users_app_subscriptions.active,
users_app_subscriptions.store,
users_app_subscriptions.expires_at,
users_app_subscriptions.reject_reason,
users_app_subscriptions.receipt_hash
FROM users_app_subscriptions;
-- +goose StatementEnd

-- +goose Down
-- +goose StatementBegin
SELECT 'down SQL query - drop view app_subs_view';
DROP VIEW app_subs_view;
-- +goose StatementEnd
82 changes: 82 additions & 0 deletions db/migrations/20240125120000_add_ratelimits.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
-- +goose Up
-- +goose StatementBegin
SELECT 'up SQL query - add table api_ratelimits';
CREATE TABLE IF NOT EXISTS
api_ratelimits (
user_id INT NOT NULL,
second INT NOT NULL DEFAULT 0,
hour INT NOT NULL DEFAULT 0,
month INT NOT NULL DEFAULT 0,
valid_until TIMESTAMP WITHOUT TIME ZONE NOT NULL,
changed_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,
PRIMARY KEY (user_id)
);

CREATE INDEX IF NOT EXISTS idx_api_ratelimits_changed_at_valid_until ON api_ratelimits (changed_at, valid_until);

SELECT 'up SQL query - add table api_keys';
CREATE TABLE IF NOT EXISTS
api_keys (
api_key VARCHAR(256) NOT NULL UNIQUE,
user_id INT NOT NULL,
valid_until TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT '9999-12-31 23:59:59',
changed_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (api_key)
);

CREATE INDEX IF NOT EXISTS idx_api_keys_changed_at_valid_until ON api_keys (changed_at, valid_until);

SELECT 'up SQL query - add table api_weights';
CREATE TABLE IF NOT EXISTS
api_weights (
bucket VARCHAR(20) NOT NULL,
endpoint TEXT NOT NULL,
method TEXT NOT NULL,
params TEXT NOT NULL,
weight INT NOT NULL DEFAULT 1,
valid_from TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT TO_TIMESTAMP(0),
PRIMARY KEY (endpoint, valid_from)
);

SELECT 'up SQL query - add table api_products';
CREATE TABLE IF NOT EXISTS
api_products (
name VARCHAR(20) NOT NULL,
stripe_price_id VARCHAR(256) NOT NULL DEFAULT '',
second INT NOT NULL DEFAULT 0,
hour INT NOT NULL DEFAULT 0,
month INT NOT NULL DEFAULT 0,
valid_from TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT TO_TIMESTAMP(0),
PRIMARY KEY (name, valid_from)
);
INSERT INTO api_products (name, second, hour, month) VALUES
('nokey', 2, 1000, 0),
('free', 10, 0, 0),
('unlimited', 100, 0, 0)
ON CONFLICT DO NOTHING;

ALTER TABLE api_statistics ADD COLUMN IF NOT EXISTS endpoint TEXT NOT NULL DEFAULT '';
ALTER TABLE api_statistics DROP CONSTRAINT IF EXISTS api_statistics_pkey;
ALTER TABLE api_statistics ADD PRIMARY KEY (ts, apikey, endpoint);
ALTER TABLE api_statistics ALTER COLUMN call SET DEFAULT '';
-- +goose StatementEnd

-- +goose Down
-- +goose StatementBegin
SELECT 'down SQL query - drop table api_ratelimits';
DROP TABLE IF EXISTS api_ratelimits;
SELECT 'down SQL query - drop index idx_api_ratelimits_changed_at';
DROP INDEX IF EXISTS idx_api_ratelimits_changed_at;
SELECT 'down SQL query - drop table api_keys';
DROP TABLE IF EXISTS api_keys;
SELECT 'down SQL query - drop index idx_api_keys_changed_at';
DROP INDEX IF EXISTS idx_api_keys_changed_at;
SELECT 'down SQL query - drop table api_weights';
DROP TABLE IF EXISTS api_weights;
SELECT 'down SQL query - drop table api_products';
DROP TABLE IF EXISTS api_products;
SELECT 'down SQL query - drop column api_statistics.endpoint';
ALTER TABLE api_statistics DROP COLUMN IF EXISTS endpoint;
ALTER TABLE api_statistics DROP CONSTRAINT IF EXISTS api_statistics_pkey;
ALTER TABLE api_statistics ADD PRIMARY KEY (ts, apikey, call);
-- +goose StatementEnd
26 changes: 13 additions & 13 deletions handlers/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"eth2-exporter/db"
"eth2-exporter/mail"
"eth2-exporter/ratelimit"
"eth2-exporter/services"
"eth2-exporter/templates"
"eth2-exporter/types"
Expand Down Expand Up @@ -87,19 +88,18 @@ func UserSettings(w http.ResponseWriter, r *http.Request) {
statsSharing = false
}

maxDaily := utils.Config.Frontend.Ratelimits.FreeDay
maxMonthly := utils.Config.Frontend.Ratelimits.FreeMonth
if subscription.PriceID != nil {
if *subscription.PriceID == utils.Config.Frontend.Stripe.Sapphire {
maxDaily = utils.Config.Frontend.Ratelimits.SapphierDay
maxMonthly = utils.Config.Frontend.Ratelimits.SapphierMonth
} else if *subscription.PriceID == utils.Config.Frontend.Stripe.Emerald {
maxDaily = utils.Config.Frontend.Ratelimits.EmeraldDay
maxMonthly = utils.Config.Frontend.Ratelimits.EmeraldMonth
} else if *subscription.PriceID == utils.Config.Frontend.Stripe.Diamond {
maxDaily = utils.Config.Frontend.Ratelimits.DiamondDay
maxMonthly = utils.Config.Frontend.Ratelimits.DiamondMonth
}
rl, err := ratelimit.DBGetUserApiRateLimit(int64(user.UserID))
if err != nil {
logger.Errorf("Error retrieving the api-ratelimit for user: %v %v", user.UserID, err)
utils.SetFlash(w, r, "", "Error: Something went wrong.")
http.Redirect(w, r, "/user/settings", http.StatusSeeOther)
return
}

maxDaily := int(rl.Second * 24 * 3600)
maxMonthly := int(rl.Month)
if maxDaily > maxMonthly {
maxDaily = maxMonthly
}

userSettingsData.ApiStatistics = &types.ApiStatistics{}
Expand Down
17 changes: 16 additions & 1 deletion local-deployment/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ services:
<<: *default-service
profiles:
- build-once
command: /bin/bash -c "git config --global --add safe.directory '*' && make -B all"
command: /bin/bash -c "git config --global --add safe.directory '*' && make -j -B all"
indexer:
<<: *default-service
command: go run ./cmd/explorer -config /app/local-deployment/config.yml
Expand All @@ -35,3 +35,18 @@ services:
command: go run ./cmd/explorer -config /app/local-deployment/config.yml
environment:
- FRONTEND_ENABLED=true
ratelimits-updater:
<<: *default-service
command: go run ./cmd/misc -config /app/local-deployment/config.yml -command=update-ratelimits
misc:
<<: *default-service
command: /bin/bash -c "while true; do date; sleep 1; done"
redis-sessions:
image: redis:7
volumes:
- redis-sessions:/data
ports:
- "$REDIS_SESSIONS_PORT:6379"

volumes:
redis-sessions:
2 changes: 1 addition & 1 deletion local-deployment/network-params.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"electra_fork_epoch": 999999999
},
"global_client_log_level": "info",
"start_tx_spammer": true,
"start_tx_spammer": false,
"start_blob_spammer": false
}

11 changes: 11 additions & 0 deletions local-deployment/provision-explorer-config.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#! /bin/bash

CL_PORT=$(kurtosis enclave inspect my-testnet | grep 4000/tcp | tr -s ' ' | cut -d " " -f 6 | sed -e 's/http\:\/\/127.0.0.1\://' | head -n 1)
echo "CL Node port is $CL_PORT"

Expand All @@ -8,6 +9,9 @@ echo "EL Node port is $EL_PORT"
REDIS_PORT=$(kurtosis enclave inspect my-testnet | grep 6379/tcp | tr -s ' ' | cut -d " " -f 6 | sed -e 's/tcp\:\/\/127.0.0.1\://' | head -n 1)
echo "Redis port is $REDIS_PORT"

REDIS_SESSIONS_PORT=$(comm -23 <(seq 49152 65535 | sort) <(ss -Htan | awk '{print $4}' | cut -d':' -f2 | sort -u) | shuf | head -n 1)
echo "Redis sessions port is $REDIS_SESSIONS_PORT"

POSTGRES_PORT=$(kurtosis enclave inspect my-testnet | grep 5432/tcp | tr -s ' ' | cut -d " " -f 6 | sed -e 's/postgresql\:\/\/127.0.0.1\://' | head -n 1)
echo "Postgres port is $POSTGRES_PORT"

Expand All @@ -18,6 +22,7 @@ cat <<EOF > .env
CL_PORT=$CL_PORT
EL_PORT=$EL_PORT
REDIS_PORT=$REDIS_PORT
REDIS_SESSIONS_PORT=$REDIS_SESSIONS_PORT
POSTGRES_PORT=$POSTGRES_PORT
LBT_PORT=$LBT_PORT
EOF
Expand Down Expand Up @@ -56,6 +61,7 @@ bigtable:
eth1ErigonEndpoint: 'http://127.0.0.1:$EL_PORT'
eth1GethEndpoint: 'http://127.0.0.1:$EL_PORT'
redisCacheEndpoint: '127.0.0.1:$REDIS_PORT'
redisSessionStoreEndpoint: '127.0.0.1:$REDIS_SESSIONS_PORT'
tieredCacheProvider: 'redis'
frontend:
siteDomain: "localhost:8080"
Expand Down Expand Up @@ -91,6 +97,11 @@ frontend:
termsOfServiceUrl: "tos.pdf"
privacyPolicyUrl: "privacy.pdf"
imprintTemplate: '{{ define "js" }}{{ end }}{{ define "css" }}{{ end }}{{ define "content" }}Imprint{{ end }}'
stripe:
sapphire: price_sapphire
emerald: price_emerald
diamond: price_diamond
ratelimitUpdateInterval: 1s

indexer:
# fullIndexOnStartup: false # Perform a one time full db index on startup
Expand Down
29 changes: 25 additions & 4 deletions local-deployment/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,48 @@ fn_main() {
start) shift; fn_start "$@"; exit;;
stop) shift; fn_stop "$@"; exit;;
sql) shift; fn_sql "$@"; exit;;
redis) shift; fn_redis "$@"; exit;;
misc) shift; fn_misc "$@"; exit;;
*) echo "$var_help"
esac
shift
done
}

fn_misc() {
docker compose exec misc go run ./cmd/misc -config /app/local-deployment/config.yml $@
}

fn_sql() {
PGPASSWORD=pass psql -h localhost -p$POSTGRES_PORT -U postgres -d db
if [ -z "${1}" ]; then
PGPASSWORD=pass psql -h localhost -p$POSTGRES_PORT -U postgres -d db
else
PGPASSWORD=pass psql -h localhost -p$POSTGRES_PORT -U postgres -d db -c "$@" --csv --pset=pager=off
fi
}

fn_redis() {
if [ -z "${1}" ]; then
docker compose exec redis-sessions redis-cli
else
docker compose exec redis-sessions redis-cli "$@"
fi
#redis-cli -h localhost -p $REDIS_PORT
}

fn_start() {
fn_stop
kurtosis run --enclave my-testnet . "$(cat network-params.json)"
# build once before starting all services to prevent multiple parallel builds
docker compose --profile=build-once run build-once &
kurtosis run --enclave my-testnet . "$(cat network-params.json)" &
wait
bash provision-explorer-config.sh
docker compose --profile=build-once run build-once # build once before starting all services to prevent multiple parallel builds
docker compose up -d
echo "Waiting for explorer to start, then browse http://localhost:8080"
}

fn_stop() {
docker compose down
docker compose down -v
kurtosis clean -a
}

Expand Down
Loading
Loading