@kyve/core-beta
Version:
🚀 The base KYVE node implementation.
83 lines (82 loc) • 3.96 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.canPropose = void 0;
const utils_1 = require("../../utils");
const INFINITY_LOOP = true;
/**
* canPropose checks if the node is able to propose the next
* bundle proposal by calling a special chain query called "canPropose".
* It runs indefinitely until the query returns a valid response
*
* @method canPropose
* @param {Node} this
* @param {number} updatedAt the last update time of the current bundle proposal
* @return {Promise<boolean>}
*/
async function canPropose(updatedAt) {
var _a;
try {
const canPropose = await (0, utils_1.callWithBackoffStrategy)(async () => {
await this.syncPoolState();
// get the index from where the bundle should get created
const fromIndex = parseInt(this.pool.data.current_index) +
parseInt(this.pool.bundle_proposal.bundle_size);
// abort if staker is the current uploader
if (this.pool.bundle_proposal.next_uploader !== this.staker) {
return {
possible: false,
reason: "Node is not next uploader of this bundle proposal",
};
}
// abort if a new bundle proposal was found
if (parseInt(this.pool.bundle_proposal.updated_at) > updatedAt) {
return {
possible: false,
reason: "New bundle proposal was found",
};
}
// loop until a valid response has been returned. The invalid
// response here is the "upload interval not surpassed". If the query
// returns an "upload interval not surpassed" that usually
// means we have to wait for the next block in the blockchain
// because the chain time only updates on every new block
while (INFINITY_LOOP) {
this.logger.debug(`this.lcd.kyve.query.v1beta1.canPropose({pool_id: ${this.poolId.toString()},staker: ${this.staker},proposer: ${this.client.account.address},from_index: ${fromIndex.toString()}})`);
const canPropose = await this.lcd.kyve.query.v1beta1.canPropose({
pool_id: this.poolId.toString(),
staker: this.staker,
proposer: this.client.account.address,
from_index: fromIndex.toString(),
});
// wait until a new block with an updated block time has been
// produced by the blockchain
if (!canPropose.possible &&
canPropose.reason.endsWith("upload interval not surpassed")) {
await (0, utils_1.sleep)(1000);
continue;
}
return canPropose;
}
}, { limitTimeoutMs: 5 * 60 * 1000, increaseByMs: 10 * 1000 }, async (err, ctx) => {
this.logger.info(`Requesting query canPropose was unsuccessful. Retrying in ${(ctx.nextTimeoutInMs / 1000).toFixed(2)}s ...`);
this.logger.debug((0, utils_1.standardizeJSON)(err));
this.m.query_can_propose_failed.inc();
});
this.logger.debug(JSON.stringify(canPropose));
this.m.query_can_propose_successful.inc();
if (canPropose === null || canPropose === void 0 ? void 0 : canPropose.possible) {
this.logger.info(`Can propose next bundle proposal`);
return true;
}
else {
this.logger.info(`Skipping proposal. Reason: ${(_a = canPropose === null || canPropose === void 0 ? void 0 : canPropose.reason) !== null && _a !== void 0 ? _a : "unknown"}`);
return false;
}
}
catch (err) {
this.logger.error(`Failed to call canPropose`);
this.logger.error((0, utils_1.standardizeJSON)(err));
return false;
}
}
exports.canPropose = canPropose;