From f69016082dc2640a261e9f6a0caf630d2811c078 Mon Sep 17 00:00:00 2001 From: "aleksej.paschenko" Date: Tue, 10 Oct 2023 14:50:59 +0300 Subject: [PATCH] Optimize liteapi.Client.GetTransactions() and improve tests --- .github/workflows/test.yaml | 1 + liteapi/client.go | 14 +++++++++++--- liteapi/client_test.go | 35 ++++++++++++++++++++++++++--------- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 486fb1f1..65bdf718 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -21,6 +21,7 @@ jobs: - name: test env: LD_LIBRARY_PATH: ${{ github.workspace }}/libs + LITE_SERVERS: ${{ secrets.LITE_SERVERS }} run: | mkdir -p ${{ env.LD_LIBRARY_PATH}} wget https://github.com/tonkeeper/tongo/raw/master/lib/linux/libemulator.so -O ${{ env.LD_LIBRARY_PATH}}/libemulator.so diff --git a/liteapi/client.go b/liteapi/client.go index 93a150ce..9c70f6fb 100644 --- a/liteapi/client.go +++ b/liteapi/client.go @@ -24,6 +24,11 @@ import ( const ( LiteServerEnvName = "LITE_SERVERS" defaultMaxConnectionsNumber = 1 + + // maxTransactionCount specifies a maximum number of transactions that can be requested from a lite server. + // This is a limitation of lite server: + // https://github.com/ton-blockchain/ton/blob/v2023.06/validator/impl/liteserver.hpp#L70 + maxTransactionCount = 16 ) var ( @@ -628,13 +633,17 @@ func (c *Client) GetLastTransactions(ctx context.Context, a ton.AccountID, limit if err != nil { return nil, err } - lastLt, lastHash := state.LastTransLt, state.LastTransHash var res []ton.Transaction + lastLt, lastHash := state.LastTransLt, state.LastTransHash for { if lastLt == 0 { break } - txs, err := c.GetTransactions(ctx, 10, a, lastLt, ton.Bits256(lastHash)) + transactionCount := maxTransactionCount + if limit-len(res) < transactionCount { + transactionCount = limit - len(res) + } + txs, err := c.GetTransactions(ctx, uint32(transactionCount), a, lastLt, ton.Bits256(lastHash)) if err != nil { if e, ok := err.(liteclient.LiteServerErrorC); ok && int32(e.Code) == -400 { // liteserver can store not full history. in that case it return error -400 for old transactions break @@ -650,7 +659,6 @@ func (c *Client) GetLastTransactions(ctx context.Context, a ton.AccountID, limit break } lastLt, lastHash = res[len(res)-1].PrevTransLt, res[len(res)-1].PrevTransHash - } return res, nil } diff --git a/liteapi/client_test.go b/liteapi/client_test.go index b4486f44..bbfbaec0 100644 --- a/liteapi/client_test.go +++ b/liteapi/client_test.go @@ -33,19 +33,36 @@ func TestNewClient_WithMaxConnectionsNumber(t *testing.T) { } func TestGetTransactions(t *testing.T) { - t.Skip() //TODO: switch tests to archive node - tongoClient, err := NewClientWithDefaultMainnet() + if len(os.Getenv("LITE_SERVERS")) == 0 { + t.Skip("LITE_SERVERS env is not set") + } + tongoClient, err := NewClient(Mainnet(), FromEnvs()) if err != nil { log.Fatalf("Unable to create tongo client: %v", err) } - accountId, _ := ton.AccountIDFromRaw("-1:34517C7BDF5187C55AF4F8B61FDC321588C7AB768DEE24B006DF29106458D7CF") - var lt uint64 = 33973842000003 - hash := ton.MustParseHash("8005AF92C0854B5A614427206673D120EA2914468C11C8F867F43740D6B4ACFB") - tx, err := tongoClient.GetTransactions(context.Background(), 100, accountId, lt, hash) - if err != nil { - log.Fatalf("Get transaction error: %v", err) + accountId, _ := ton.AccountIDFromRaw("0:2cf3b5b8c891e517c9addbda1c0386a09ccacbb0e3faf630b51cfc8152325acb") + for i := 1; i < 77; i++ { + txs, err := tongoClient.GetLastTransactions(context.Background(), accountId, i) + if err != nil { + t.Fatalf("Get transaction error: %v", err) + } + if len(txs) != i { + t.Fatalf("expected #txs: %v, got: %v", i, len(txs)) + } + hashes := make(map[string]struct{}, len(txs)) + for i, tx := range txs { + if i > 0 { + if txs[i-1].Lt <= tx.Lt { + log.Fatalf("wrong order") + } + } + s := tx.Hash().Hex() + if _, ok := hashes[s]; ok { + log.Fatalf("duplicated hash: %v", s) + } + hashes[s] = struct{}{} + } } - fmt.Printf("Tx qty: %v\n", len(tx)) } func TestSendRawMessage(t *testing.T) {