// Use strict "use strict"; // Classes // Consensus class class Consensus { // Public // Initialize static initialize() { // Update saved wallet type and network type Consensus.getWalletType(); Consensus.getNetworkType(); } // Get wallet type static getWalletType() { // Check if consensus's wallet type doesn't exist if(typeof Consensus.walletType === "undefined") { // Check if not not a web worker and local storage is usable if((typeof self === "undefined" || typeof WorkerGlobalScope === "undefined" || self instanceof WorkerGlobalScope === false) && typeof localStorage !== "undefined") { // Get the saved wallet type var walletType = localStorage.getItem(Consensus.WALLET_TYPE_LOCAL_STORAGE_NAME); // Check if wallet type doesn't exist or isn't valid if(walletType === Common.INVALID_LOCAL_STORAGE_ITEM || Number.isNaN(parseInt(walletType, Common.DECIMAL_NUMBER_BASE)) === true) { // Set wallet type to the default wallet type walletType = Consensus.DEFAULT_WALLET_TYPE; } // Otherwise else { // Get wallet type in the correct format walletType = parseInt(walletType, Common.DECIMAL_NUMBER_BASE); // Check if the wallet type doesn't exist if(walletType < Consensus.MWC_WALLET_TYPE || walletType > Consensus.EPIC_WALLET_TYPE) { // Set wallet type to the default wallet type walletType = Consensus.DEFAULT_WALLET_TYPE; } } } // Otherwise else { // Set wallet type to the default wallet type var walletType = Consensus.DEFAULT_WALLET_TYPE; } // Get URL parameters var urlParameters = Common.getUrlParameters(); // Check if override wallet type exists if(Consensus.OVERRIDE_WALLET_TYPE_URL_PARAMETER_NAME in urlParameters === true) { // Check override wallet type switch(urlParameters[Consensus.OVERRIDE_WALLET_TYPE_URL_PARAMETER_NAME]) { // MWC wallet case Consensus.WALLET_MWC_TEXT_VALUE: // Set wallet type to MWC wallet type walletType = Consensus.MWC_WALLET_TYPE; // Break break; // GRIN wallet case Consensus.WALLET_GRIN_TEXT_VALUE: // Set wallet type to GRIN wallet type walletType = Consensus.GRIN_WALLET_TYPE; // Break break; // EPIC wallet case Consensus.WALLET_EPIC_TEXT_VALUE: // Set wallet type to EPIC wallet type walletType = Consensus.EPIC_WALLET_TYPE; // Break break; } } // Check if not not a web worker and local storage is usable if((typeof self === "undefined" || typeof WorkerGlobalScope === "undefined" || self instanceof WorkerGlobalScope === false) && typeof localStorage !== "undefined") { // Check if saved wallet type needs to be updated if(walletType.toFixed() !== localStorage.getItem(Consensus.WALLET_TYPE_LOCAL_STORAGE_NAME)) { // Try try { // Save wallet type in local storage localStorage.setItem(Consensus.WALLET_TYPE_LOCAL_STORAGE_NAME, walletType.toFixed()); } // Catch errors catch(error) { } } } // Set consensus's wallet type Consensus.walletType = walletType; } // Return consensus's wallet type return Consensus.walletType; } // Get network type static getNetworkType() { // Check if consensus's network type doesn't exist if(typeof Consensus.networkType === "undefined") { // Check if not not a web worker and local storage is usable if((typeof self === "undefined" || typeof WorkerGlobalScope === "undefined" || self instanceof WorkerGlobalScope === false) && typeof localStorage !== "undefined") { // Get the saved network type var networkType = localStorage.getItem(Consensus.NETWORK_TYPE_LOCAL_STORAGE_NAME); // Check if network type doesn't exist or isn't valid if(networkType === Common.INVALID_LOCAL_STORAGE_ITEM || Number.isNaN(parseInt(networkType, Common.DECIMAL_NUMBER_BASE)) === true) { // Set network type to the default network type networkType = Consensus.DEFAULT_NETWORK_TYPE; } // Otherwise else { // Get network type in the correct format networkType = parseInt(networkType, Common.DECIMAL_NUMBER_BASE); // Check if the network type doesn't exist if(networkType < Consensus.MAINNET_NETWORK_TYPE || networkType > Consensus.TESTNET_NETWORK_TYPE) { // Set network type to the default network type networkType = Consensus.DEFAULT_NETWORK_TYPE; } } } // Otherwise else { // Set network type to the default network type var networkType = Consensus.DEFAULT_NETWORK_TYPE; } // Get URL parameters var urlParameters = Common.getUrlParameters(); // Check if override network type exists if(Consensus.OVERRIDE_NETWORK_TYPE_URL_PARAMETER_NAME in urlParameters === true) { // Check override network type switch(urlParameters[Consensus.OVERRIDE_NETWORK_TYPE_URL_PARAMETER_NAME]) { // Mainnet network case Consensus.NETWORK_MAINNET_TEXT_VALUE: // Set network type to mainnet network type networkType = Consensus.MAINNET_NETWORK_TYPE; // Break break; // Testnet network case Consensus.NETWORK_TESTNET_TEXT_VALUE: // Check wallet type switch(Consensus.getWalletType()) { // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Set network type to testnet network type networkType = Consensus.TESTNET_NETWORK_TYPE; // Break break; } // Break break; // Floonet network case Consensus.NETWORK_FLOONET_TEXT_VALUE: // Check wallet type switch(Consensus.getWalletType()) { // MWC or EPIC wallet case Consensus.MWC_WALLET_TYPE: case Consensus.EPIC_WALLET_TYPE: // Set network type to testnet network type networkType = Consensus.TESTNET_NETWORK_TYPE; // Break break; } // Break break; } } // Check if not not a web worker and local storage is usable if((typeof self === "undefined" || typeof WorkerGlobalScope === "undefined" || self instanceof WorkerGlobalScope === false) && typeof localStorage !== "undefined") { // Check if saved network type needs to be updated if(networkType.toFixed() !== localStorage.getItem(Consensus.NETWORK_TYPE_LOCAL_STORAGE_NAME)) { // Try try { // Save network type in local storage localStorage.setItem(Consensus.NETWORK_TYPE_LOCAL_STORAGE_NAME, networkType.toFixed()); } // Catch errors catch(error) { } } } // Set consensus's network type Consensus.networkType = networkType; } // Return consensus's network type return Consensus.networkType; } // Wallet type to text static walletTypeToText(walletType) { // Check wallet type switch(walletType) { // MWC wallet type case Consensus.MWC_WALLET_TYPE: // Return MWC wallet text value return Consensus.WALLET_MWC_TEXT_VALUE; // GRIN wallet type case Consensus.GRIN_WALLET_TYPE: // Return GRIN wallet text value return Consensus.WALLET_GRIN_TEXT_VALUE; // EPIC wallet type case Consensus.EPIC_WALLET_TYPE: // Return EPIC wallet text value return Consensus.WALLET_EPIC_TEXT_VALUE; } } // Network type to text static networkTypeToText(networkType) { // Check network type switch(networkType) { // Mainnet network type case Consensus.MAINNET_NETWORK_TYPE: // Return mainnet network text value return Consensus.NETWORK_MAINNET_TEXT_VALUE; // Testnet network type case Consensus.TESTNET_NETWORK_TYPE: // Check wallet type switch(Consensus.getWalletType()) { // MWC or EPIC wallet case Consensus.MWC_WALLET_TYPE: case Consensus.EPIC_WALLET_TYPE: // Return floonet network text value return Consensus.NETWORK_FLOONET_TEXT_VALUE; // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Return testnet network text value return Consensus.NETWORK_TESTNET_TEXT_VALUE; } } } // Get reward static getReward(isMainnet, fees, height) { // Get block reward at height var reward = Consensus.getBlockReward(isMainnet, height); // Add fee to reward reward = reward.plus(fees); // Return reward return reward; } // Is valid header version static isValidHeaderVersion(isMainnet, height, version) { // Return if version is valid at height while taking hard forks into account return version.isEqualTo(Consensus.getHeaderVersion(isMainnet, height)) === true; } // Is no recent duplicate kernel enabled static isNoRecentDuplicateKernelsEnabled(isMainnet) { // Check wallet type switch(Consensus.getWalletType()) { // MWC wallet case Consensus.MWC_WALLET_TYPE: // Check if is mainnet if(isMainnet === true) { // Return false return false; } // Otherwise else { // TODO Support no recent duplicate kernels return false; } // Break break; // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Check if is mainnet if(isMainnet === true) { // Return false return false; } // Otherwise else { // TODO Support no recent duplicate kernels return false; } // Break break; // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Return false return false; } } // Block time seconds static get BLOCK_TIME_SECONDS() { // Return block time seconds return 60; } // Block height minute static get BLOCK_HEIGHT_MINUTE() { // Return block height minute return Math.floor(Common.SECONDS_IN_A_MINUTE / Consensus.BLOCK_TIME_SECONDS); } // Block height hour static get BLOCK_HEIGHT_HOUR() { // Return block height hour return Common.MINUTES_IN_AN_HOUR * Consensus.BLOCK_HEIGHT_MINUTE; } // Block height day static get BLOCK_HEIGHT_DAY() { // Return block height day return Common.HOURS_IN_A_DAY * Consensus.BLOCK_HEIGHT_HOUR; } // Block height week static get BLOCK_HEIGHT_WEEK() { // Return block height week return Common.DAYS_IN_A_WEEK * Consensus.BLOCK_HEIGHT_DAY; } // Block height year static get BLOCK_HEIGHT_YEAR() { // Return block height year return Common.WEEKS_IN_A_YEAR * Consensus.BLOCK_HEIGHT_WEEK; } // Coinbase maturity static get COINBASE_MATURITY() { // Return coinbase maturity return Consensus.BLOCK_HEIGHT_DAY; } // First block height static get FIRST_BLOCK_HEIGHT() { // Return first block height return 0; } // Value number base static get VALUE_NUMBER_BASE() { // Check wallet type switch(Consensus.getWalletType()) { // MWC or GRIN wallet case Consensus.MWC_WALLET_TYPE: case Consensus.GRIN_WALLET_TYPE: // Return value number base return 1E9; // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Return value number base return 1E8; } } // Currency name static get CURRENCY_NAME() { // Check wallet type switch(Consensus.getWalletType()) { // MWC wallet case Consensus.MWC_WALLET_TYPE: // Return currency name return "MWC"; // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Return currency name return "GRIN"; // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Return currency name return "EPIC"; } } // Slatepack address human-readable part static get SLATEPACK_ADDRESS_HUMAN_READABLE_PART() { // Check wallet type switch(Consensus.getWalletType()) { // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Check network type switch(Consensus.getNetworkType()) { // Mainnet network type case Consensus.MAINNET_NETWORK_TYPE: // Return Slatepack address human-readable part return "grin"; // Testnet network type case Consensus.TESTNET_NETWORK_TYPE: // Return Slatepack address human-readable part return "tgrin"; } } } // MWC wallet type static get MWC_WALLET_TYPE() { // Return MWC wallet type return 0; } // GRIN wallet type static get GRIN_WALLET_TYPE() { // Return GRIN wallet type return Consensus.MWC_WALLET_TYPE + 1; } // EPIC wallet type static get EPIC_WALLET_TYPE() { // Return EPIC wallet type return Consensus.GRIN_WALLET_TYPE + 1; } // Mainnet network type static get MAINNET_NETWORK_TYPE() { // Return mainnet network type return 0; } // Testnet type static get TESTNET_NETWORK_TYPE() { // Return testnet network type return Consensus.MAINNET_NETWORK_TYPE + 1; } // Legacy header version static get LEGACY_HEADER_VERSION() { // Check wallet type switch(Consensus.getWalletType()) { // MWC or GRIN wallet case Consensus.MWC_WALLET_TYPE: case Consensus.GRIN_WALLET_TYPE: // Return legacy header version return new BigNumber(1); // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Return legacy header version return new BigNumber(6); } } // Block input weight static get BLOCK_INPUT_WEIGHT() { // Return block input weight return 1; } // Block output weight static get BLOCK_OUTPUT_WEIGHT() { // Return block output weight return 21; } // Block kernel weight static get BLOCK_KERNEL_WEIGHT() { // Return block kernel weight return 3; } // Maximum block weight static get MAXIMUM_BLOCK_WEIGHT() { // Return maximum block weight return 40000; } // BIP44 coin type static get BIP44_COIN_TYPE() { // Check wallet type switch(Consensus.getWalletType()) { // MWC wallet case Consensus.MWC_WALLET_TYPE: // Check network type switch(Consensus.getNetworkType()) { // Mainnet network case Consensus.MAINNET_NETWORK_TYPE: // Return BIP44 coin type return 593; // Testnet network case Consensus.TESTNET_NETWORK_TYPE: // Return BIP44 coin type return 1; } // Break break; // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Check network type switch(Consensus.getNetworkType()) { // Mainnet network case Consensus.MAINNET_NETWORK_TYPE: // Return BIP44 coin type return 592; // Testnet network case Consensus.TESTNET_NETWORK_TYPE: // Return BIP44 coin type return 1; } // Break break; // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Check network type switch(Consensus.getNetworkType()) { // Mainnet network case Consensus.MAINNET_NETWORK_TYPE: // Return BIP44 coin type return 23000; // Testnet network case Consensus.TESTNET_NETWORK_TYPE: // Return BIP44 coin type return 1; } // Break break; } } // Explorer kernel excess URL static get EXPLORER_KERNEL_EXCESS_URL() { // Check wallet type switch(Consensus.getWalletType()) { // MWC wallet case Consensus.MWC_WALLET_TYPE: // Check network type switch(Consensus.getNetworkType()) { // Mainnet network case Consensus.MAINNET_NETWORK_TYPE: // Return explorer kernel excess URL return "https://explorer.mwc.mw/#k"; // Testnet network case Consensus.TESTNET_NETWORK_TYPE: // Return explorer kernel excess URL return "https://explorer.floonet.mwc.mw/#k"; } // Break break; // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Check network type switch(Consensus.getNetworkType()) { // Mainnet network case Consensus.MAINNET_NETWORK_TYPE: // Return no explorer URL return Consensus.NO_EXPLORER_URL; // Testnet network case Consensus.TESTNET_NETWORK_TYPE: // Return no explorer URL return Consensus.NO_EXPLORER_URL; } // Break break; // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Check network type switch(Consensus.getNetworkType()) { // Mainnet network case Consensus.MAINNET_NETWORK_TYPE: // Return no explorer URL return Consensus.NO_EXPLORER_URL; // Testnet network case Consensus.TESTNET_NETWORK_TYPE: // Return no explorer URL return Consensus.NO_EXPLORER_URL; } // Break break; } } // Explorer output commitment URL static get EXPLORER_OUTPUT_COMMITMENT_URL() { // Check wallet type switch(Consensus.getWalletType()) { // MWC wallet case Consensus.MWC_WALLET_TYPE: // Check network type switch(Consensus.getNetworkType()) { // Mainnet network case Consensus.MAINNET_NETWORK_TYPE: // Return explorer output commitment URL return "https://explorer.mwc.mw/#o"; // Testnet network case Consensus.TESTNET_NETWORK_TYPE: // Return explorer output commitment URL return "https://explorer.floonet.mwc.mw/#o"; } // Break break; // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Check network type switch(Consensus.getNetworkType()) { // Mainnet network case Consensus.MAINNET_NETWORK_TYPE: // Return no explorer URL return Consensus.NO_EXPLORER_URL; // Testnet network case Consensus.TESTNET_NETWORK_TYPE: // Return no explorer URL return Consensus.NO_EXPLORER_URL; } // Break break; // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Check network type switch(Consensus.getNetworkType()) { // Mainnet network case Consensus.MAINNET_NETWORK_TYPE: // Return explorer output commitment URL return "https://explorer.epiccash.com/blockdetail/"; // Testnet network case Consensus.TESTNET_NETWORK_TYPE: // Return no explorer URL return Consensus.NO_EXPLORER_URL; } // Break break; } } // No explorer URL static get NO_EXPLORER_URL() { // Return no explorer URL return null; } // Hardware waller starting height static get HARDWARE_WALLET_STARTING_HEIGHT() { // Check wallet type switch(Consensus.getWalletType()) { // MWC wallet case Consensus.MWC_WALLET_TYPE: // Check network type switch(Consensus.getNetworkType()) { // Mainnet network case Consensus.MAINNET_NETWORK_TYPE: // Return hardware wallet starting height return 1239928; // Testnet network case Consensus.TESTNET_NETWORK_TYPE: // Return hardware wallet starting height return 1115028; } // Break break; // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Check network type switch(Consensus.getNetworkType()) { // Mainnet network case Consensus.MAINNET_NETWORK_TYPE: // Return hardware wallet starting height return 1687446; // Testnet network case Consensus.TESTNET_NETWORK_TYPE: // Return hardware wallet starting height return 1195819; } // Break break; // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Check network type switch(Consensus.getNetworkType()) { // Mainnet network case Consensus.MAINNET_NETWORK_TYPE: // Return hardware wallet starting height return 1943415; // Testnet network case Consensus.TESTNET_NETWORK_TYPE: // Return hardware wallet starting height return 0; } // Break break; } } // Private // Get block reward static getBlockReward(isMainnet, height) { // Check wallet type switch(Consensus.getWalletType()) { // MWC wallet case Consensus.MWC_WALLET_TYPE: // Check if height is the first block height if(height.isEqualTo(Consensus.FIRST_BLOCK_HEIGHT) === true) // Return genesis block reward return new BigNumber("10000000041800000"); // Otherwise check if height is less than the second block offset else if(height.isLessThan(Consensus.getEpochBlockOffset(isMainnet, 2)) === true) // Return reward during the first epoch range return new BigNumber(2380952380); // Otherwise check if height is less than the third block offset else if(height.isLessThan(Consensus.getEpochBlockOffset(isMainnet, 3)) === true) // Return reward during the second epoch range return new BigNumber(600000000); // Otherwise check if height is less than the fourth block offset else if(height.isLessThan(Consensus.getEpochBlockOffset(isMainnet, 4)) === true) // Return reward during the third epoch range return new BigNumber(450000000); // Otherwise check if height is less than the fifth block offset else if(height.isLessThan(Consensus.getEpochBlockOffset(isMainnet, 5)) === true) // Return reward during the fourth epoch range return new BigNumber(300000000); // Otherwise check if height is less than the sixth block offset else if(height.isLessThan(Consensus.getEpochBlockOffset(isMainnet, 6)) === true) // Return reward during the fifth epoch range return new BigNumber(250000000); // Otherwise check if height is less than the seventh block offset else if(height.isLessThan(Consensus.getEpochBlockOffset(isMainnet, 7)) === true) // Return reward during the sixth epoch range return new BigNumber(200000000); // Otherwise check if height is less than the eighth block offset else if(height.isLessThan(Consensus.getEpochBlockOffset(isMainnet, 8)) === true) // Return reward during the seventh epoch range return new BigNumber(150000000); // Otherwise check if height is less than the ninth block offset else if(height.isLessThan(Consensus.getEpochBlockOffset(isMainnet, 9)) === true) // Return reward during the eighth epoch range return new BigNumber(100000000); // Otherwise check if height is less than the tenth block offset else if(height.isLessThan(Consensus.getEpochBlockOffset(isMainnet, 10)) === true) // Return reward during the ninth epoch range return new BigNumber(50000000); // Otherwise check if height is less than the eleventh block offset else if(height.isLessThan(Consensus.getEpochBlockOffset(isMainnet, 11)) === true) // Return reward during the tenth epoch range return new BigNumber(25000000); // Otherwise check if height is less than the eleventh block offset plus the eleventh epoch duration else if(height.isLessThan(Consensus.getEpochBlockOffset(isMainnet, 11).plus(Consensus.getEpochDuration(isMainnet, 11))) === true) // Return reward during the eleventh epoch range return new BigNumber(10000000); // Otherwise check if height is equal to the eleventh block offset plus the eleventh epoch duration else if(height.isEqualTo(Consensus.getEpochBlockOffset(isMainnet, 11).plus(Consensus.getEpochDuration(isMainnet, 11))) === true) // Return reward during the twelfth epoch range return new BigNumber(2211980); // Otherwise else // Return zero return new BigNumber(0); // Break break; // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Return block reward return new BigNumber("60000000000"); // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Check if is mainnet if(isMainnet === true) { // Check if height is the first block era if(height.isLessThanOrEqualTo(Consensus.FIRST_BLOCK_ERA_HEIGHT) === true) { // Return reward during the first block era return new BigNumber("1600000000"); } // Otherwise check if height is the second block era else if(height.isLessThanOrEqualTo(Consensus.SECOND_BLOCK_ERA_HEIGHT) === true) { // Return reward during the second block era return new BigNumber("800000000"); } // Otherwise check if height is the third block era else if(height.isLessThanOrEqualTo(Consensus.THIRD_BLOCK_ERA_HEIGHT) === true) { // Return reward during the third block era return new BigNumber("400000000"); } // Otherwise check if height is the fourth block era else if(height.isLessThanOrEqualTo(Consensus.FOURTH_BLOCK_ERA_HEIGHT) === true) { // Return reward during the fourth block era return new BigNumber("200000000"); } // Otherwise check if height is the fifth block era else if(height.isLessThanOrEqualTo(Consensus.FIFTH_BLOCK_ERA_HEIGHT) === true) { // Return reward during the fifth block era return new BigNumber("100000000"); } // Otherwise else { // Get height after fifth era var heightAfterFifthEra = height.minus(Consensus.FIFTH_BLOCK_ERA_HEIGHT + 1); // Return reward during current era return (new BigNumber("15625000")).dividedToIntegerBy((new BigNumber(2)).exponentiatedBy(heightAfterFifthEra.dividedToIntegerBy(Consensus.SIXTH_AND_UP_BLOCK_ERA_INTERVAL))); } } // Otherwise else { // Check if height is the first block era if(height.isLessThanOrEqualTo(Consensus.FIRST_BLOCK_ERA_HEIGHT) === true) { // Return reward during the first block era return new BigNumber("1600000000"); } // Otherwise else { // Return reward during the second block era return new BigNumber("800000000"); } } // Break break; } } // Get epoch duration static getEpochDuration(isMainnet, epoch) { // Check wallet type switch(Consensus.getWalletType()) { // MWC wallet case Consensus.MWC_WALLET_TYPE: // Check epoch switch(epoch) { // One case 1: // Return duration of first epoch return 0; // Two case 2: // Return duration of second epoch return (isMainnet === true) ? 120 * Consensus.BLOCK_HEIGHT_DAY : Consensus.BLOCK_HEIGHT_DAY; // Three case 3: // Return duration of third epoch return (isMainnet === true) ? 60 * Consensus.BLOCK_HEIGHT_DAY : Consensus.BLOCK_HEIGHT_DAY; // Four case 4: // Return duration of fourth epoch return 120 * Consensus.BLOCK_HEIGHT_DAY; // Five case 5: // Return duration of fifth epoch return 180 * Consensus.BLOCK_HEIGHT_DAY; // Six case 6: // Return duration of sixth epoch return 180 * Consensus.BLOCK_HEIGHT_DAY; // Seven case 7: // Return duration of seventh epoch return Consensus.BLOCK_HEIGHT_YEAR; // Eight case 8: // Return duration of eighth epoch return Consensus.BLOCK_HEIGHT_YEAR; // Nine case 9: // Return duration of ninth epoch return 6 * Consensus.BLOCK_HEIGHT_YEAR; // Tenth case 10: // Return duration of tenth epoch return 10 * Consensus.BLOCK_HEIGHT_YEAR; // Eleven case 11: // Return duration of eleventh epoch return 876349148; } } } // Get epoch block offset static getEpochBlockOffset(isMainnet, epoch) { // Check wallet type switch(Consensus.getWalletType()) { // MWC wallet case Consensus.MWC_WALLET_TYPE: // Set offset to the C31 hard fork height var offset = Consensus.getC31HardForkHeight(isMainnet); // Check if past second epoch range if(epoch >= 2) // Add initial block duration to offset offset = offset.plus((isMainnet === true) ? Consensus.BLOCK_HEIGHT_WEEK : Consensus.BLOCK_HEIGHT_DAY); // Go through all remaining epoch ranges for(var i = 3; i <= epoch; ++i) // Add epoch's block duration to offset offset = offset.plus(Consensus.getEpochDuration(isMainnet, i - 1)); // Return offset return offset; } } // Get C31 hard fork height static getC31HardForkHeight(isMainnet) { // Check wallet type switch(Consensus.getWalletType()) { // MWC wallet case Consensus.MWC_WALLET_TYPE: // Return C31 hard fork height return (isMainnet === true) ? new BigNumber(202500) : new BigNumber(270000); } } // Get header version static getHeaderVersion(isMainnet, height) { // Check wallet type switch(Consensus.getWalletType()) { // MWC wallet case Consensus.MWC_WALLET_TYPE: // Check if height is less than the C31 hard fork height if(height.isLessThan(Consensus.getC31HardForkHeight(isMainnet)) === true) // Return legacy header version return Consensus.LEGACY_HEADER_VERSION; // Otherwise else // Return second header version return Consensus.LEGACY_HEADER_VERSION.plus(1); // Break break; // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Check if mainnet if(isMainnet === true) { // Get header version based on number of hard forks var headerVersion = height.dividedToIntegerBy(Consensus.HARD_FORK_INTERVAL).plus(1); // Check if header version is greater than the maximum header version if(headerVersion.isGreaterThan(Consensus.MAXIMUM_HEADER_VERSION) === true) // Set header version to the maximum header version headerVersion = new BigNumber(Consensus.MAXIMUM_HEADER_VERSION); // Return header version return headerVersion; } // Otherwise else { // Check is height is less than first hard fork height if(height.isLessThan(Consensus.FIRST_HARD_FORK_HEIGHT) === true) // Return legacy header version return Consensus.LEGACY_HEADER_VERSION; // Otherwise check if height is less than second hard fork height else if(height.isLessThan(Consensus.SECOND_HARD_FORK_HEIGHT) === true) // Return second header version return Consensus.LEGACY_HEADER_VERSION.plus(1); // Otherwise check if height is less than third hard fork height else if(height.isLessThan(Consensus.THIRD_HARD_FORK_HEIGHT) === true) // Return third header version return Consensus.LEGACY_HEADER_VERSION.plus(2); // Otherwise check if height is less than fourth hard forks height else if(height.isLessThan(Consensus.FOURTH_HARD_FORK_HEIGHT) === true) // Return fourth header version return Consensus.LEGACY_HEADER_VERSION.plus(3); // Otherwise else // Return fifth header version return Consensus.LEGACY_HEADER_VERSION.plus(4); } // Break break; // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Check if height is less than the first hard fork height if(height.isLessThan(Consensus.getFirstHardForkHeight(isMainnet)) === true) // Return legacy header version return Consensus.LEGACY_HEADER_VERSION; // Otherwise else // Return second header version return Consensus.LEGACY_HEADER_VERSION.plus(1); // Break break; } } // Get first hard fork height static getFirstHardForkHeight(isMainnet) { // Check wallet type switch(Consensus.getWalletType()) { // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Return first hard fork height return (isMainnet === true) ? new BigNumber(9000000) : new BigNumber(25800); } } // Hard fork interval static get HARD_FORK_INTERVAL() { // Check wallet type switch(Consensus.getWalletType()) { // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Return hard fork interval return Math.floor(Consensus.BLOCK_HEIGHT_YEAR / 2); } } // First hard fork height static get FIRST_HARD_FORK_HEIGHT() { // Check wallet type switch(Consensus.getWalletType()) { // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Return first hard fork height return 185040; } } // Second hard fork height static get SECOND_HARD_FORK_HEIGHT() { // Check wallet type switch(Consensus.getWalletType()) { // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Return second hard fork height return 298080; } } // Third hard fork height static get THIRD_HARD_FORK_HEIGHT() { // Check wallet type switch(Consensus.getWalletType()) { // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Return third hard fork height return 552960; } } // Fourth hard fork height static get FOURTH_HARD_FORK_HEIGHT() { // Check wallet type switch(Consensus.getWalletType()) { // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Return fourth hard fork height return 642240; } } // Maximum header version static get MAXIMUM_HEADER_VERSION() { // Check wallet type switch(Consensus.getWalletType()) { // GRIN wallet case Consensus.GRIN_WALLET_TYPE: // Return maximum header version return 5; } } // Default Wallet type static get DEFAULT_WALLET_TYPE() { // Return default wallet type return Consensus.MWC_WALLET_TYPE; } // Default network type static get DEFAULT_NETWORK_TYPE() { // Return default network type return Consensus.MAINNET_NETWORK_TYPE; } // Wallet MWC text value static get WALLET_MWC_TEXT_VALUE() { // Return wallet MWC text value return (typeof Language !== "undefined") ? Language.getDefaultTranslation('MimbleWimble Coin') : "MimbleWimble Coin"; } // Wallet GRIN value static get WALLET_GRIN_TEXT_VALUE() { // Return wallet GRIN text value return (typeof Language !== "undefined") ? Language.getDefaultTranslation('Grin') : "Grin"; } // Wallet EPIC value static get WALLET_EPIC_TEXT_VALUE() { // Return wallet EPIC text value return (typeof Language !== "undefined") ? Language.getDefaultTranslation('Epic Cash') : "Epic Cash"; } // Network mainnet value static get NETWORK_MAINNET_TEXT_VALUE() { // Return network mainnet text value return (typeof Language !== "undefined") ? Language.getDefaultTranslation('Mainnet') : "Mainnet"; } // Network floonet value static get NETWORK_FLOONET_TEXT_VALUE() { // Return network floonet text value return (typeof Language !== "undefined") ? Language.getDefaultTranslation('Floonet') : "Floonet"; } // Network testnet value static get NETWORK_TESTNET_TEXT_VALUE() { // Return network testnet text value return (typeof Language !== "undefined") ? Language.getDefaultTranslation('Testnet') : "Testnet"; } // Override wallet type URL parameter name static get OVERRIDE_WALLET_TYPE_URL_PARAMETER_NAME() { // Return override wallet type URL parameter name return "Override Wallet Type"; } // Override network type URL parameter name static get OVERRIDE_NETWORK_TYPE_URL_PARAMETER_NAME() { // Return override network type URL parameter name return "Override Network Type"; } // First block era height static get FIRST_BLOCK_ERA_HEIGHT() { // Check wallet type switch(Consensus.getWalletType()) { // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Return first block era height return 334 * Consensus.BLOCK_HEIGHT_DAY; } } // Second block era height static get SECOND_BLOCK_ERA_HEIGHT() { // Check wallet type switch(Consensus.getWalletType()) { // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Return second block era height return 470 * Consensus.BLOCK_HEIGHT_DAY + Consensus.FIRST_BLOCK_ERA_HEIGHT; } } // Third block era height static get THIRD_BLOCK_ERA_HEIGHT() { // Check wallet type switch(Consensus.getWalletType()) { // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Return third block era height return 601 * Consensus.BLOCK_HEIGHT_DAY + Consensus.SECOND_BLOCK_ERA_HEIGHT; } } // Fourth block era height static get FOURTH_BLOCK_ERA_HEIGHT() { // Check wallet type switch(Consensus.getWalletType()) { // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Return fourth block era height return 800 * Consensus.BLOCK_HEIGHT_DAY + Consensus.THIRD_BLOCK_ERA_HEIGHT; } } // Fifth block era height static get FIFTH_BLOCK_ERA_HEIGHT() { // Check wallet type switch(Consensus.getWalletType()) { // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Return fifth block era height return 1019 * Consensus.BLOCK_HEIGHT_DAY + Consensus.FOURTH_BLOCK_ERA_HEIGHT; } } // Sixth and up block era interval static get SIXTH_AND_UP_BLOCK_ERA_INTERVAL() { // Check wallet type switch(Consensus.getWalletType()) { // EPIC wallet case Consensus.EPIC_WALLET_TYPE: // Return sixth and up block era interval return 1460 * Consensus.BLOCK_HEIGHT_DAY; } } // Wallet type local storage name static get WALLET_TYPE_LOCAL_STORAGE_NAME() { // Return wallet type local storage name return "Wallet Type"; } // Network type local storage name static get NETWORK_TYPE_LOCAL_STORAGE_NAME() { // Return network type local storage name return "Network Type"; } } // Main function // Set global object's consensus globalThis["Consensus"] = Consensus; // Check if not not a web worker if(typeof self === "undefined" || typeof WorkerGlobalScope === "undefined" || self instanceof WorkerGlobalScope === false) { // Initialize consensus Consensus.initialize(); }