mokka
Version:
Mokka Consensus Algorithm implementation in Javascript
84 lines • 3.26 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.NodeModel = void 0;
const events_1 = require("events");
const EventTypes_1 = __importDefault(require("../constants/EventTypes"));
const NodeStates_1 = __importDefault(require("../constants/NodeStates"));
class NodeModel extends events_1.EventEmitter {
constructor(privateKey, multiaddr, crashModel = 'CFT', state = NodeStates_1.default.FOLLOWER) {
super();
this.nodes = new Map();
this.lastLeadersPublicKeyInTermMap = new Map();
this._term = 0;
this.lastTermUpdateTime = 0;
this._leaderPublicKey = '';
this._proofMintedTime = 0;
this.privateKey = privateKey;
this.publicKey = multiaddr.match(/\w+$/).toString();
this._state = state;
this.nodeAddress = multiaddr.split(/\w+$/)[0].replace(/\/$/, '');
this.crashModel = crashModel;
}
get state() {
return this._state;
}
get term() {
return this._term;
}
get leaderPublicKey() {
return this._leaderPublicKey;
}
get address() {
return this.nodeAddress;
}
get proof() {
return this._proof;
}
majority() {
const clusterSize = this.nodes.size + 1; // peer nodes + self
return clusterSize - Math.ceil((clusterSize - 1) / (this.crashModel === 'CFT' ? 2 : 3));
}
write(address, packet) {
throw new Error('should be implemented!');
}
setState(state, term = this._term, leaderPublicKey, proof = null, proofMintedTime = 0) {
this._state = state;
if (this._term !== term) {
this.lastTermUpdateTime = Date.now();
}
this._term = term;
this._leaderPublicKey = leaderPublicKey;
this._proof = proof;
this._proofMintedTime = proofMintedTime;
this.emit(EventTypes_1.default.STATE);
if (this.leaderPublicKey) {
if (this.lastLeadersPublicKeyInTermMap.size >= this.majority() - 1) {
const prevTermsToRemove = [...this.lastLeadersPublicKeyInTermMap.keys()].sort()
.slice(this.lastLeadersPublicKeyInTermMap.size - this.majority());
for (const prevTerm of prevTermsToRemove) {
this.lastLeadersPublicKeyInTermMap.delete(prevTerm);
}
}
this.lastLeadersPublicKeyInTermMap.set(term, leaderPublicKey);
}
}
getProofMintedTime() {
return this._proofMintedTime;
}
checkPublicKeyCanBeLeaderNextRound(publicKey) {
const values = [...this.lastLeadersPublicKeyInTermMap.values()];
return !values.includes(publicKey);
}
checkTermNumber(term) {
if (!this.lastTermUpdateTime) {
return true;
}
const maxPossibleTerm = this._term + Math.ceil((Date.now() - this.lastTermUpdateTime) / this.heartbeat * 1.5);
return maxPossibleTerm >= term;
}
}
exports.NodeModel = NodeModel;
//# sourceMappingURL=NodeModel.js.map