diff --git a/liteapi/pool/connection.go b/liteapi/pool/connection.go index 9f83e55a..241cfcdc 100644 --- a/liteapi/pool/connection.go +++ b/liteapi/pool/connection.go @@ -56,18 +56,7 @@ func (c *connection) Run(ctx context.Context, detectArchive bool) { } c.SetMasterHead(head) for { - if err := c.client.WaitMasterchainSeqno(ctx, head.Seqno+1, 15_000); err != nil { - // TODO: log error - time.Sleep(1000 * time.Millisecond) - // we want to request seqno again with LiteServerGetMasterchainInfo - // to avoid situation when this server has been offline for too long, - // and it doesn't contain a block with the latest known seqno anymore. - break - } - if ctx.Err() != nil { - return - } - res, err := c.client.LiteServerGetMasterchainInfo(ctx) + res, err := c.client.WaitMasterchainBlock(ctx, head.Seqno+1, 15_000) if err != nil { // TODO: log error time.Sleep(1000 * time.Millisecond) @@ -79,7 +68,7 @@ func (c *connection) Run(ctx context.Context, detectArchive bool) { if ctx.Err() != nil { return } - head = res.Last.ToBlockIdExt() + head = res.Id.ToBlockIdExt() c.SetMasterHead(head) } } diff --git a/liteclient/client.go b/liteclient/client.go index 5dc82464..f805d0fd 100644 --- a/liteclient/client.go +++ b/liteclient/client.go @@ -227,3 +227,50 @@ func (c *Client) WaitMasterchainSeqno(ctx context.Context, seqno uint32, timeout func (c *Client) AverageRoundTrip() time.Duration { return c.connection.AverageRoundTrip() } + +func (c *Client) WaitMasterchainBlock(ctx context.Context, seqno uint32, timeout uint32) (res LiteServerBlockHeaderC, err error) { + var ( + mc int = -1 + uintMc uint32 = uint32(mc) + ) + request := LiteServerLookupBlockRequest{ + Mode: 1, + Id: TonNodeBlockIdC{ + Workchain: uintMc, + Shard: 0x8000000000000000, + Seqno: seqno, + }, + } + data := make([]byte, 0, 38) + data = binary.LittleEndian.AppendUint32(data, magicLiteServerWaitMasterchainSeqno) + data = binary.LittleEndian.AppendUint32(data, seqno) + data = binary.LittleEndian.AppendUint32(data, timeout) + payload, err := tl.Marshal(struct { + tl.SumType + Req LiteServerLookupBlockRequest `tlSumType:"fac8f71e"` + }{SumType: "Req", Req: request}) + if err != nil { + return res, err + } + data = append(data, payload...) + resp, err := c.liteServerRequest(ctx, data) + if err != nil { + return res, err + } + if len(resp) < 4 { + return res, fmt.Errorf("not enough bytes for tag") + } + tag := binary.LittleEndian.Uint32(resp[:4]) + if tag == 0xbba9e148 { + var errRes LiteServerErrorC + if err = tl.Unmarshal(bytes.NewReader(resp[4:]), &errRes); err != nil { + return res, err + } + return res, errRes + } + if tag == 0x752d8219 { + err = tl.Unmarshal(bytes.NewReader(resp[4:]), &res) + return res, err + } + return res, fmt.Errorf("invalid tag") +} diff --git a/liteclient/client_test.go b/liteclient/client_test.go index e8c1a8b4..20a82b42 100644 --- a/liteclient/client_test.go +++ b/liteclient/client_test.go @@ -228,3 +228,25 @@ func TestGeneratedMethod6(t *testing.T) { fmt.Printf("Address: %s Queue size: %d\n", addr.String(), a.Size) } } + +func TestClient_WaitMasterchainBlock(t *testing.T) { + c, err := createTestLiteServerConnection() + if err != nil { + t.Fatalf("NewConnection() failed: %v", err) + } + client := NewClient(c) + resp, err := client.LiteServerGetMasterchainInfo(context.Background()) + if err != nil { + t.Fatalf("LiteServerGetMasterchainInfo() failed: %v", err) + } + seqno := resp.Last.Seqno + 2 + //fmt.Printf("Current seqno: %d waiting seqno: %d\n", resp.Last.Seqno, seqno) + resp1, err := client.WaitMasterchainBlock(context.Background(), seqno, 15000) + if err != nil { + t.Fatalf("WaitMasterchainSeqno() failed: %v", err) + } + //fmt.Printf("Result seqno: %d\n", resp1.Id.Seqno) + if resp1.Id.Seqno != seqno { + t.Fatalf("Invalid result seqno") + } +}