@polkassembly/util
Version:
Set of utility functions for Polkassembly and more.
142 lines (141 loc) • 5.33 kB
JavaScript
"use strict";
// Copyright 2019-2020 @paritytech/polkassembly authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var bn_js_1 = __importDefault(require("bn.js"));
var newton_raphson_1 = require("./newton-raphson");
var solveQuadraticEquation_1 = require("./solveQuadraticEquation");
var types_1 = require("./types");
var ONE = new bn_js_1.default(1);
var TWO = new bn_js_1.default(2);
var THREE = new bn_js_1.default(3);
var TEN = new bn_js_1.default(10);
var MAX_ITERATIONS = 20;
var getFAndFp = function (_a) {
var totalIssuance = _a.totalIssuance, votes = _a.votes, votesWithoutConviction = _a.votesWithoutConviction;
return {
f: function (x) {
// with v: votes, vc: votes without conviction, t: total issuance
// x^3 + v*x^2 - (vc)^2 * t
return x.pow(THREE).add(votesWithoutConviction.mul(x.pow(TWO))).sub(votes.pow(TWO).mul(totalIssuance));
},
fp: function (x) {
// 3*x^2 + 2*v*x
return THREE.mul(x.pow(TWO)).add(TWO.mul(votesWithoutConviction).mul(x));
}
};
};
var raphsonIterations = function (f, fp) {
var initialGuess = ONE;
var result = { foundRoot: false };
var i = 1;
while (!result.foundRoot && i < MAX_ITERATIONS) {
result = newton_raphson_1.newtonRaphson(f, fp, initialGuess.mul(TEN).pow(new bn_js_1.default(i)));
i++;
}
return result;
};
/**
* @name getFailingThreshold
* @summary Calculates amount of nays needed for a referendum to fail
**/
function getFailingThreshold(_a) {
var ayes = _a.ayes, ayesWithoutConviction = _a.ayesWithoutConviction, totalIssuance = _a.totalIssuance, threshold = _a.threshold;
if (ayes.isZero() || ayesWithoutConviction.isZero()) {
// there is no vote against, any number of aye>0 would work
return {
failingThreshold: ONE,
isValid: true
};
}
// if there are more ayes
// than the (total issuance) /2 it can't fail
if (ayesWithoutConviction.gt(totalIssuance.divn(2))) {
return {
isValid: false
};
}
if (threshold === types_1.VoteThresholdEnum.Simplemajority) {
return {
failingThreshold: ayes,
isValid: true
};
}
if (threshold === types_1.VoteThresholdEnum.Supermajorityrejection) {
var _b = getFAndFp({ totalIssuance: totalIssuance, votes: ayes, votesWithoutConviction: ayesWithoutConviction }), f = _b.f, fp = _b.fp;
var result = raphsonIterations(f, fp);
return result.foundRoot
? {
failingThreshold: result.result,
isValid: true
}
: {
isValid: false
};
}
else {
// SuperMajorityRejection
// with v: votes, vc: votes without conviction, t: total issuance
// -t*x^2 + v^2*x + (v)^2*vc
var res = solveQuadraticEquation_1.solveQuadraticEquation(totalIssuance.neg(), ayes.pow(TWO), ayes.pow(TWO).mul(ayesWithoutConviction));
return {
failingThreshold: bn_js_1.default.max(res[0], res[1]),
isValid: true
};
}
}
exports.getFailingThreshold = getFailingThreshold;
/**
* @name getPassingThreshold
* @summary Calculates amount of ayes needed for a referendum to pass
**/
function getPassingThreshold(_a) {
var nays = _a.nays, naysWithoutConviction = _a.naysWithoutConviction, totalIssuance = _a.totalIssuance, threshold = _a.threshold;
if (nays.isZero() || naysWithoutConviction.isZero()) {
// there is no vote against, any number of aye>0 would work
return {
isValid: true,
passingThreshold: ONE
};
}
// if there are more nays
// than the (total issuance) /2 it can't pass
if (naysWithoutConviction.gt(totalIssuance.divn(2))) {
return {
isValid: false
};
}
if (threshold === types_1.VoteThresholdEnum.Simplemajority) {
return {
isValid: true,
passingThreshold: nays
};
}
if (threshold === types_1.VoteThresholdEnum.Supermajorityapproval) {
var _b = getFAndFp({ totalIssuance: totalIssuance, votes: nays, votesWithoutConviction: naysWithoutConviction }), f = _b.f, fp = _b.fp;
var result = raphsonIterations(f, fp);
return result.foundRoot
? {
isValid: true,
passingThreshold: result.result
}
: {
isValid: false
};
}
else {
// SuperMajorityRejection
// with v: votes, vc: votes without conviction, t: total issuance
// -t*x^2 + v^2*x + (v)^2*vc
var res = solveQuadraticEquation_1.solveQuadraticEquation(totalIssuance.neg(), nays.pow(TWO), nays.pow(TWO).mul(naysWithoutConviction));
return {
isValid: true,
passingThreshold: bn_js_1.default.max(res[0], res[1])
};
}
}
exports.getPassingThreshold = getPassingThreshold;