Skip to content

Commit 0fe7812

Browse files
authored
Merge pull request #39 from gobicycle/develop
rate limiter
2 parents b305b29 + 2fea022 commit 0fe7812

File tree

9 files changed

+64
-10
lines changed

9 files changed

+64
-10
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ For more information on Jettons compatibility, see [Jettons compatibility](/jett
7676
|------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
7777
| `LITESERVER` | IP and port of lite server, example: `185.86.76.183:5815` |
7878
| `LITESERVER_KEY` | public key of lite server `5v2dHtSclsGsZVbNVwTj4hQDso5xvQjzL/yPEHJevHk=`. <br/>Be careful with base64 encoding and ENV var. Use '' |
79+
| `LITESERVER_RATE_LIMIT` | If you have a rented node with an RPS limit, set the RPS value here equal to (or preferably slightly less than) the limit. Default: 100. |
7980
| `SEED` | seed phrase for main hot wallet. 24 words compatible with standard TON wallets |
8081
| `DB_URI` | URI for DB connection, example: <br/>`postgresql://db_user:db_password@localhost:5432/payment_processor` |
8182
| `POSTGRES_DB` | name of database for storing payments data |

blockchain/blockchain.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ type contract struct {
5353
}
5454

5555
// NewConnection creates new Blockchain connection
56-
func NewConnection(addr, key string) (*Connection, error) {
56+
func NewConnection(addr, key string, rateLimit int) (*Connection, error) {
5757

5858
client := liteclient.NewConnectionPool()
5959
ctx, cancel := context.WithTimeout(context.Background(), time.Second*120)
@@ -64,6 +64,8 @@ func NewConnection(addr, key string) (*Connection, error) {
6464
return nil, fmt.Errorf("connection err: %v", err.Error())
6565
}
6666

67+
limitedClient := newLimitedClient(client, rateLimit)
68+
6769
var wrappedClient ton.APIClientWrapped
6870

6971
if config.Config.ProofCheckEnabled {
@@ -77,7 +79,7 @@ func NewConnection(addr, key string) (*Connection, error) {
7779
return nil, fmt.Errorf("get network config from url err: %s", err.Error())
7880
}
7981

80-
wrappedClient = ton.NewAPIClient(client, ton.ProofCheckPolicySecure).WithRetry()
82+
wrappedClient = ton.NewAPIClient(limitedClient, ton.ProofCheckPolicySecure).WithRetry()
8183
wrappedClient.SetTrustedBlockFromConfig(cfg)
8284

8385
log.Infof("Fetching and checking proofs since config init block ...")
@@ -88,7 +90,7 @@ func NewConnection(addr, key string) (*Connection, error) {
8890
log.Infof("Proof checks are completed")
8991

9092
} else {
91-
wrappedClient = ton.NewAPIClient(client, ton.ProofCheckPolicyUnsafe).WithRetry()
93+
wrappedClient = ton.NewAPIClient(limitedClient, ton.ProofCheckPolicyUnsafe).WithRetry()
9294
}
9395

9496
// TODO: replace after tonutils fix

blockchain/blockchain_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func connect(t *testing.T) *Connection {
3030
if key == "" {
3131
t.Fatal("empty key var")
3232
}
33-
c, err := NewConnection(server, key)
33+
c, err := NewConnection(server, key, 100)
3434
if err != nil {
3535
t.Fatal("connections err: ", err)
3636
}

blockchain/limited_client.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package blockchain
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/xssnick/tonutils-go/tl"
8+
"github.com/xssnick/tonutils-go/ton"
9+
"golang.org/x/time/rate"
10+
)
11+
12+
type limitedLiteClient struct {
13+
limiter *rate.Limiter
14+
original ton.LiteClient
15+
}
16+
17+
func newLimitedClient(lc ton.LiteClient, rateLimit int) *limitedLiteClient {
18+
return &limitedLiteClient{
19+
original: lc,
20+
limiter: rate.NewLimiter(rate.Limit(rateLimit), 1),
21+
}
22+
}
23+
24+
func (w *limitedLiteClient) QueryLiteserver(ctx context.Context, payload tl.Serializable, result tl.Serializable) error {
25+
err := w.limiter.Wait(ctx)
26+
if err != nil {
27+
return fmt.Errorf("limiter err: %w", err)
28+
}
29+
return w.original.QueryLiteserver(ctx, payload, result)
30+
}
31+
32+
func (w *limitedLiteClient) StickyContext(ctx context.Context) context.Context {
33+
return w.original.StickyContext(ctx)
34+
}
35+
36+
func (w *limitedLiteClient) StickyNodeID(ctx context.Context) uint32 {
37+
return w.original.StickyNodeID(ctx)
38+
}
39+
40+
func (w *limitedLiteClient) StickyContextNextNode(ctx context.Context) (context.Context, error) {
41+
return w.original.StickyContextNextNode(ctx)
42+
}
43+
44+
func (w *limitedLiteClient) StickyContextNextNodeBalanced(ctx context.Context) (context.Context, error) {
45+
return w.original.StickyContextNextNodeBalanced(ctx)
46+
}

cmd/processor/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func main() {
3232
signal.Notify(sigChannel, os.Interrupt, syscall.SIGTERM)
3333
wg := new(sync.WaitGroup)
3434

35-
bcClient, err := blockchain.NewConnection(config.Config.LiteServer, config.Config.LiteServerKey)
35+
bcClient, err := blockchain.NewConnection(config.Config.LiteServer, config.Config.LiteServerKey, config.Config.LiteServerRateLimit)
3636
if err != nil {
3737
log.Fatalf("blockchain connection error: %v", err)
3838
}

cmd/testutil/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func main() {
5151
log.Fatalf("invalid HOT_WALLET_B env var")
5252
}
5353

54-
bcClient, err := blockchain.NewConnection(config.Config.LiteServer, config.Config.LiteServerKey)
54+
bcClient, err := blockchain.NewConnection(config.Config.LiteServer, config.Config.LiteServerKey, config.Config.LiteServerRateLimit)
5555
if err != nil {
5656
log.Fatalf("blockchain connection error: %v", err)
5757
}

config/config.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
package config
22

33
import (
4+
"log"
5+
"math/big"
6+
"strings"
7+
"time"
8+
49
"github.com/caarlos0/env/v6"
510
"github.com/shopspring/decimal"
611
"github.com/tonkeeper/tongo/boc"
712
"github.com/xssnick/tonutils-go/address"
813
"github.com/xssnick/tonutils-go/tlb"
9-
"log"
10-
"math/big"
11-
"strings"
12-
"time"
1314
)
1415

1516
const MaxJettonForwardTonAmount = 20_000_000
@@ -39,6 +40,7 @@ const MaxCommentLength = 1000 // qty in chars
3940
var Config = struct {
4041
LiteServer string `env:"LITESERVER,required"`
4142
LiteServerKey string `env:"LITESERVER_KEY,required"`
43+
LiteServerRateLimit int `env:"LITESERVER_RATE_LIMIT" envDefault:"100"`
4244
Seed string `env:"SEED,required"`
4345
DatabaseURI string `env:"DB_URI,required"`
4446
APIPort int `env:"API_PORT,required"`

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212
github.com/sirupsen/logrus v1.9.3
1313
github.com/tonkeeper/tongo v1.9.9
1414
github.com/xssnick/tonutils-go v1.10.2
15+
golang.org/x/time v0.10.0
1516
)
1617

1718
require (

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
196196
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
197197
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
198198
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
199+
golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
200+
golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
199201
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
200202
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
201203
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=

0 commit comments

Comments
 (0)