Skip to content
Closed
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
4 changes: 4 additions & 0 deletions faucet/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/gnolang/gno v0.0.0-20230914214026-ef6a55bf9db2
github.com/peterbourgon/ff/v3 v3.4.0
github.com/redis/go-redis/v9 v9.2.0
github.com/stretchr/testify v1.8.4
go.uber.org/zap v1.26.0
golang.org/x/sync v0.3.0
)
Expand All @@ -16,6 +17,7 @@ require (
github.com/btcsuite/btcd/btcutil v1.0.0 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgraph-io/badger/v3 v3.2103.4 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
Expand All @@ -36,6 +38,7 @@ require (
github.com/linxGnu/grocksdb v1.8.4 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rs/cors v1.10.0 // indirect
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
go.etcd.io/bbolt v1.3.7 // indirect
Expand All @@ -46,4 +49,5 @@ require (
golang.org/x/net v0.15.0 // indirect
golang.org/x/sys v0.12.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
5 changes: 5 additions & 0 deletions faucet/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 39 additions & 8 deletions faucet/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,21 +220,21 @@ func execMain(cfg *rootCfg) error {
// Create the client (HTTP)
cli := tm2Client.NewClient(cfg.remote)

redisOpts, err := redis.ParseURL(cfg.redisURL)
if err != nil {
return err
}
redisClient := redis.NewClient(redisOpts)

// Prepare the middlewares
middlewares := []faucet.Middleware{
prepareFundMiddleware(cli, fundLimit),
prepareFundMiddleware(cli, fundLimit, redisClient),
}

// TODO temporary
if len(cfg.allowedTokens) != 0 {
middlewares = append(middlewares, prepareTokenListMiddleware(cfg.allowedTokens))
} else {
redisOpts, err := redis.ParseURL(cfg.redisURL)
if err != nil {
return err
}
redisClient := redis.NewClient(redisOpts)

middlewares = append(middlewares, prepareTokenMiddleware(redisClient))
}

Expand Down Expand Up @@ -358,7 +358,7 @@ func (w *waiter) wait() error {
}

// prepareFundMiddleware prepares the fund (balance) validation middleware
func prepareFundMiddleware(client client.Client, fundLimit std.Coins) faucet.Middleware {
func prepareFundMiddleware(client client.Client, fundLimit std.Coins, redisClient *redis.Client) faucet.Middleware {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Parse the request to extract the address
Expand Down Expand Up @@ -389,6 +389,31 @@ func prepareFundMiddleware(client client.Client, fundLimit std.Coins) faucet.Mid
return
}

token := r.Context().Value("token").(string)

keys, _, err := redisClient.SScan(r.Context(), "TOKEN_ADDRESSES", 0, "*:"+request.To, 1).Result()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// DO WE REALLY WANT AN ADDRESS TO NO BE ABLE TO ASK A SECOND TIME MONEY FROM THE FAUCET ?
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm for limiting to 1 with this system, but we can give a (way too) huge amount of ugnot, i.e., good for 10k transactions.

Then, if someone hits the limit, we can manually send them additional tokens from an admin account.

WDYT?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, works fine :)

for _, k := range keys {
if strings.Contains(k, request.To) {
http.Error(w, "address already receive tokens", http.StatusInternalServerError)
return
}
}

_, err = redisClient.HSet(r.Context(), "TOKEN:"+token, "address", request.To).Result()
if err != nil {
http.Error(w, "Failed to store token address", http.StatusInternalServerError)
}

_, err = redisClient.SAdd(r.Context(), "TOKEN_ADDRESSES", token+":"+request.To).Result()
if err != nil {
http.Error(w, "Failed to store TOKEN_ADDRESSES", http.StatusInternalServerError)
}

// Extract the beneficiary address
beneficiary, err := crypto.AddressFromBech32(request.To)
if err != nil {
Expand Down Expand Up @@ -435,6 +460,9 @@ func prepareTokenListMiddleware(tokens []string) faucet.Middleware {
// Fetch the faucet token
token := r.Header.Get(tokenKey)

req := r.WithContext(context.WithValue(r.Context(), "token", token))
*r = *req

// Make sure the token is valid
if _, valid := tokenMap[token]; !valid {
http.Error(w, "Invalid faucet token", http.StatusForbidden)
Expand All @@ -455,6 +483,9 @@ func prepareTokenMiddleware(redisClient *redis.Client) faucet.Middleware {
// Fetch the faucet token
token := r.Header.Get(tokenKey)

req := r.WithContext(context.WithValue(r.Context(), "token", token))
*r = *req

res, err := redisClient.HGet(r.Context(), "TOKEN:"+token, "used").Result()
if err != nil {
http.Error(w, "Invalid faucet token", http.StatusForbidden)
Expand Down