UNPKG

@polkassembly/util

Version:

Set of utility functions for Polkassembly and more.

142 lines (141 loc) 5.33 kB
"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;