From ef74fefe846ed07bd513b1c5d13edf7d84fad0df Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 18 Aug 2020 13:05:34 +0200 Subject: [PATCH 1/2] Fall back on query when header from subscription is too high --- packages/stargate/src/queries/queryclient.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/stargate/src/queries/queryclient.ts b/packages/stargate/src/queries/queryclient.ts index d5052478..10b7723b 100644 --- a/packages/stargate/src/queries/queryclient.ts +++ b/packages/stargate/src/queries/queryclient.ts @@ -230,7 +230,7 @@ export class QueryClient { } const searchHeight = height + 1; - let nextHeader: Header; + let nextHeader: Header | undefined; let headersSubscription: Stream | undefined; try { headersSubscription = this.tmClient.subscribeNewBlockHeader(); @@ -239,9 +239,14 @@ export class QueryClient { } if (headersSubscription) { - // get the header for height+1 - nextHeader = await firstEvent(headersSubscription); // TODO: fall back on polling if this returns a too high header - } else { + const firstHeader = await firstEvent(headersSubscription); + // The first header we get might not be n+1 but n+2 or even higher. In such cases we fall back on a query. + if (firstHeader.height === searchHeight) { + nextHeader = firstHeader; + } + } + + if (!nextHeader) { // start from current height to avoid backend error for minHeight in the future let header = (await this.tmClient.blockchain(height, searchHeight)).blockMetas .map((meta) => meta.header) From ac7cd44c0fc8e9d35eb287e390315e7adce470d5 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 18 Aug 2020 13:11:34 +0200 Subject: [PATCH 2/2] Refactor code to avoid repeating query --- packages/stargate/src/queries/queryclient.ts | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/packages/stargate/src/queries/queryclient.ts b/packages/stargate/src/queries/queryclient.ts index 10b7723b..c835a816 100644 --- a/packages/stargate/src/queries/queryclient.ts +++ b/packages/stargate/src/queries/queryclient.ts @@ -246,26 +246,19 @@ export class QueryClient { } } - if (!nextHeader) { + while (!nextHeader) { // start from current height to avoid backend error for minHeight in the future - let header = (await this.tmClient.blockchain(height, searchHeight)).blockMetas + const correctHeader = (await this.tmClient.blockchain(height, searchHeight)).blockMetas .map((meta) => meta.header) .find((h) => h.height === searchHeight); - while (!header) { + if (correctHeader) { + nextHeader = correctHeader; + } else { await sleep(1000); - header = (await this.tmClient.blockchain(height, searchHeight)).blockMetas - .map((meta) => meta.header) - .find((h) => h.height === searchHeight); } - nextHeader = header; - } - - if (nextHeader.height !== searchHeight) { - throw new Error( - `Query requires header at height ${searchHeight} for proof verification, but next header was ${nextHeader.height}`, - ); } + assert(nextHeader.height === searchHeight, "Got wrong header. This is a bug in the logic above."); return nextHeader; } }