Skip to content

Commit db6da12

Browse files
authored
fix: always use finalized block header for transaction signing (#918)
* handle fetching the block header ourselves, and cache it for 6 seconds--because we have a high transaction volume, every network round trip to the node that we can save is important. * always use the finalized block for transaction signing, which should eliminated at least some problems. * eliminating the fetch of one of the block headers cuts down on network round trips to the chain RPC node.
1 parent 1cf802e commit db6da12

1 file changed

Lines changed: 21 additions & 30 deletions

File tree

libs/blockchain/src/blockchain.service.ts

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -98,28 +98,16 @@ export class BlockchainService extends BlockchainRpcQueryService implements OnAp
9898
}
9999

100100
public async updateLatestBlockHeader() {
101-
const latestHeader = await this.api.rpc.chain.getHeader();
102101
const latestFinalizedBlock = await this.api.rpc.chain.getFinalizedHead();
103102
const latestFinalizedHeader = await this.api.rpc.chain.getHeader(latestFinalizedBlock);
104-
await this.defaultRedis
105-
.multi()
106-
.set(
107-
'latestHeader',
108-
JSON.stringify({
109-
blockHash: latestHeader.hash.toHex(),
110-
number: latestHeader.number.toNumber(),
111-
parentHash: latestHeader.parentHash.toHex(),
112-
}),
113-
)
114-
.set(
115-
'latestFinalizedHeader',
116-
JSON.stringify({
117-
blockHash: latestFinalizedHeader.hash.toHex(),
118-
number: latestFinalizedHeader.number.toNumber(),
119-
parentHash: latestFinalizedHeader.parentHash.toHex(),
120-
}),
121-
)
122-
.exec();
103+
await this.defaultRedis.set(
104+
'latestFinalizedHeader',
105+
JSON.stringify({
106+
blockHash: latestFinalizedHeader.hash.toHex(),
107+
number: latestFinalizedHeader.number.toNumber(),
108+
parentHash: latestFinalizedHeader.parentHash.toHex(),
109+
}),
110+
);
123111
}
124112

125113
constructor(
@@ -323,24 +311,27 @@ export class BlockchainService extends BlockchainRpcQueryService implements OnAp
323311
* Gets the block hash and number of the latest block for signing. We cache this info & update asynchronously. This
324312
* eliminates unnecessary RPC calls to get the latest block info, since it's okay if we're a little behind in the block number/hash we
325313
* use for signing and mortality checking.
326-
* @returns The block hash & number of the latest finalized block if the finality lag is greater than the maximum allowed, otherwise the block hash of the latest block.
314+
* @returns The block hash & number of the latest finalized block
315+
*
316+
* NOTE: the polkadot-js logic that inspired this would fetch both the latest & latest finalized blocks, and choose
317+
* between them based on the block number delta compared to MAX_FINALITY_LAG. But because we're caching this and don't
318+
* really care if we're a little behind, and because issues with the fork-aware transaction pool can sometimes make this
319+
* problematic, it's better to just rely on the latest finalized block. Also, eliminating the need to get both block
320+
* headers cuts down on network round trips to the chain node.
327321
*/
328322
public async getBlockForSigning(): Promise<IHeaderInfo> {
329-
let [latestHeaderStr, finalizedHeaderStr] = await this.defaultRedis.mget(['latestHeader', 'latestFinalizedHeader']);
323+
let finalizedHeaderStr = await this.defaultRedis.get('latestFinalizedHeader');
330324

331-
if (!latestHeaderStr || !finalizedHeaderStr) {
325+
if (!finalizedHeaderStr) {
332326
await this.updateLatestBlockHeader();
333-
[latestHeaderStr, finalizedHeaderStr] = await this.defaultRedis.mget(['latestHeader', 'latestFinalizedHeader']);
327+
finalizedHeaderStr = await this.defaultRedis.get('latestFinalizedHeader');
334328
}
335329

336-
if (!latestHeaderStr || !finalizedHeaderStr) {
337-
throw new Error('Unable to get latest block header info');
330+
if (!finalizedHeaderStr) {
331+
throw new Error('Unable to get latest finalized block header info');
338332
}
339333

340-
const latestHeader = JSON.parse(latestHeaderStr) as IHeaderInfo;
341-
const finalizedHeader = JSON.parse(finalizedHeaderStr) as IHeaderInfo;
342-
343-
return latestHeader.number - finalizedHeader.number > MAX_FINALITY_LAG.toNumber() ? latestHeader : finalizedHeader;
334+
return JSON.parse(finalizedHeaderStr) as IHeaderInfo;
344335
}
345336

346337
/**

0 commit comments

Comments
 (0)