diff --git a/cmd/jsutils/getchainstatus.js b/cmd/jsutils/getchainstatus.js index 4c93a57918..17097a58d1 100644 --- a/cmd/jsutils/getchainstatus.js +++ b/cmd/jsutils/getchainstatus.js @@ -15,13 +15,14 @@ function printUsage() { console.log(" node getchainstatus.js --help"); console.log(" node getchainstatus.js [subcommand] [options]"); console.log("\nSubcommands:"); - console.log(" GetTxCount: find the block with max tx size of a range"); - console.log(" GetVersion: dump validators' binary version, based on Header.Extra"); + console.log(" GetMaxTxCountInBlockRange: find the block with max tx size of a range"); + console.log(" GetBinaryVersion: dump validators' binary version, based on Header.Extra"); console.log(" GetTopAddr: get hottest $topNum target address of a block range"); console.log(" GetSlashCount: get slash state at a specific block height"); console.log(" GetPerformanceData: analyze the performance data of a block range"); console.log(" GetBlobTxs: get BlobTxs of a block range"); console.log(" GetFaucetStatus: get faucet status of BSC testnet"); + console.log(" GetKeyParameters: dump some key governance parameter"); console.log("\nOptions:"); console.log(" --rpc specify the url of RPC endpoint"); console.log(" --startNum the start block number"); @@ -32,13 +33,14 @@ function printUsage() { console.log(" --blockNum the block number to be checked"); console.log("\nExample:"); // mainnet https://bsc-mainnet.nodereal.io/v1/454e504917db4f82b756bd0cf6317dce - console.log(" node getchainstatus.js GetTxCount --rpc https://bsc-testnet-dataseed.bnbchain.org --startNum 40000001 --endNum 40000005") - console.log(" node getchainstatus.js GetVersion --rpc https://bsc-testnet-dataseed.bnbchain.org --num 21") + console.log(" node getchainstatus.js GetMaxTxCountInBlockRange --rpc https://bsc-testnet-dataseed.bnbchain.org --startNum 40000001 --endNum 40000005") + console.log(" node getchainstatus.js GetBinaryVersion --rpc https://bsc-testnet-dataseed.bnbchain.org --num 21") console.log(" node getchainstatus.js GetTopAddr --rpc https://bsc-testnet-dataseed.bnbchain.org --startNum 40000001 --endNum 40000010 --topNum 10") - console.log(" node getchainstatus.js GetSlashCount --rpc https://bsc-testnet-dataseed.bnbchain.org --blockNum 40000001") // latest block if `--blockNum` is not specified + console.log(" node getchainstatus.js GetSlashCount --rpc https://bsc-testnet-dataseed.bnbchain.org --blockNum 40000001") // default: latest block console.log(" node getchainstatus.js GetPerformanceData --rpc https://bsc-testnet-dataseed.bnbchain.org --startNum 40000001 --endNum 40000010") console.log(" node getchainstatus.js GetBlobTxs --rpc https://bsc-testnet-dataseed.bnbchain.org --startNum 40000001 --endNum 40000010") console.log(" node getchainstatus.js GetFaucetStatus --rpc https://bsc-testnet-dataseed.bnbchain.org --startNum 40000001 --endNum 40000010") + console.log(" node getchainstatus.js GetKeyParameters --rpc https://bsc-testnet-dataseed.bnbchain.org") // default: latest block } program.usage = printUsage; @@ -46,19 +48,39 @@ program.parse(process.argv); const provider = new ethers.JsonRpcProvider(program.rpc) +const addrValidatorSet = '0x0000000000000000000000000000000000001000'; +const addrSlash = '0x0000000000000000000000000000000000001001'; +const addrStakeHub = '0x0000000000000000000000000000000000002002'; + +const validatorSetAbi = [ + "function getLivingValidators() external view returns (address[], bytes[])", + "function numOfCabinets() external view returns (uint256)", + "function maxNumOfCandidates() external view returns (uint256)", + "function maxNumOfWorkingCandidates() external view returns (uint256)", + "function maxNumOfMaintaining() external view returns (uint256)", // default 3 + "function turnLength() external view returns (uint256)", + "function systemRewardAntiMEVRatio() external view returns (uint256)", + "function maintainSlashScale() external view returns (uint256)", // default 2, valid: 1->9 + "function burnRatio() external view returns (uint256)", // default: 10% + "function systemRewardBaseRatio() external view returns (uint256)" // default: 1/16 +] const slashAbi = [ "function getSlashIndicator(address validatorAddr) external view returns (uint256, uint256)" ] -const validatorSetAbi = [ - "function getLivingValidators() external view returns (address[], bytes[])" -] + +// https://github.com/bnb-chain/bsc-genesis-contract/blob/master/contracts/StakeHub.sol const stakeHubAbi = [ + "function getValidatorElectionInfo(uint256 offset, uint256 limit) external view returns (address[], uint256[], bytes[], uint256)", "function getValidatorDescription(address validatorAddr) external view returns (tuple(string, string, string, string))", - "function consensusToOperator(address consensusAddr) public view returns (address)" + "function consensusToOperator(address consensusAddr) public view returns (address)", + "function minSelfDelegationBNB() public view returns (uint256)", // default 2000, valid: 1000 -> 100,000 + "function maxElectedValidators() public view returns (uint256)", // valid: 1 -> 500 + "function unbondPeriod() public view returns (uint256)", // default 7days, valid: 3days ->30days + "function downtimeSlashAmount() public view returns (uint256)", // default 10BNB, valid: 5 -> felonySlashAmount + "function felonySlashAmount() public view returns (uint256)", // default 200BNB, valid: > max(100, downtimeSlashAmount) + "function downtimeJailTime() public view returns (uint256)", // default 2days, + "function felonyJailTime() public view returns (uint256)" // default 30days, ] -const addrValidatorSet = '0x0000000000000000000000000000000000001000'; -const addrSlash = '0x0000000000000000000000000000000000001001'; -const addrStakeHub = '0x0000000000000000000000000000000000002002'; const validatorSet = new ethers.Contract(addrValidatorSet, validatorSetAbi, provider); const slashIndicator = new ethers.Contract(addrSlash, slashAbi, provider) @@ -120,15 +142,31 @@ const validatorMap = new Map([ ["0x1a3d9D7A717D64e6088aC937d5aAcDD3E20ca963","Elbrus"], ["0x40D3256EB0BaBE89f0ea54EDAa398513136612f5","Bloxroute"], ["0xF9a1Db0d6f22Bd78ffAECCbc8F47c83Df9FBdbCf","Test"], - ["0xB4cd0dCF71381b452A92A359BbE7146e8825Ce46","BSCLista"] + ["0xB4cd0dCF71381b452A92A359BbE7146e8825Ce46","BSCLista"], + ["0xD7b26968D8AD24f433d422b18A11a6580654Af13","TNkgnL4"], + ["0xFDA4C7E5C6005511236E24f3d5eBFd65Ffa10AED","MyHave"], + ["0x73f86c0628e04A69dcb61944F0df5DE115bA3FD8","InfStones"], + ["0xcAc5E4158fAb2eB95aA5D9c8DdfC9DF7208fDc58","My5eVal"], + ["0x96f6a2A267C726973e40cCCBB956f1716Bac7dc0","ForDc0"], + ["0x15a13e315CbfB9398A26D77a299963BF034c28F8","Blxr"], + ["0x1d622CAcd06c0eafd0a8a4C66754C96Db50cE14C","Val9B"], + ["0xd6BD505f4CFc19203875A92B897B07DE13d118ce","Panipuri"], + ["0x9532223eAa6Eb6939A00C0A39A054d93b5cCf4Af","TrustT"], + ["0xB19b6057245002442123371494372719d2Beb83D","Vtwval"], + ["0x5530Bac059E50821E7146D951e56FC7500bda007","LedgrTrus"], + ["0xEe22F03961b407bCBae66499a029Be4cA0AF4ab4","AB4"], + ["0x1AE5f5C3Cb452E042b0B7b9DC60596C9CD84BaF6","Jake"], + ["0xfA4d592F9B152f7a10B5DE9bE24C27a74BCE431A","MyTWFMM"] ]); -// 1.cmd: "GetTxCount", usage: -// node getchainstatus.js GetTxCount --rpc https://bsc-testnet-dataseed.bnbchain.org \ + + +// 1.cmd: "GetMaxTxCountInBlockRange", usage: +// node getchainstatus.js GetMaxTxCountInBlockRange --rpc https://bsc-testnet-dataseed.bnbchain.org \ // --startNum 40000001 --endNum 40000005 \ // --miner(optional): specified: find the max txCounter from the specified validator, // not specified: find the max txCounter from all validators -async function getTxCount() { +async function getMaxTxCountInBlockRange() { let txCount = 0; let num = 0; console.log("Find the max txs count between", program.startNum, "and", program.endNum); @@ -150,8 +188,8 @@ async function getTxCount() { console.log("BlockNum = ", num, "TxCount =", txCount); } -// 2.cmd: "GetVersion", usage: -// node getchainstatus.js GetVersion \ +// 2.cmd: "GetBinaryVersion", usage: +// node getchainstatus.js GetBinaryVersion \ // --rpc https://bsc-testnet-dataseed.bnbchain.org \ // --num(optional): defualt 21, the number of blocks that will be checked async function getBinaryVersion() { @@ -223,6 +261,17 @@ async function getTopAddr() { // node getchainstatus.js GetSlashCount \ // --rpc https://bsc-testnet-dataseed.bnbchain.org \ // --blockNum(optional): the block num which is based for the slash state, default: latest block +async function getValidatorMoniker(consensusAddr, blockNum) { + if (validatorMap.has(consensusAddr)) { + return validatorMap.get(consensusAddr) + } + let opAddr = await stakeHub.consensusToOperator(consensusAddr, {blockTag:blockNum}) + let desc = await stakeHub.getValidatorDescription(opAddr, {blockTag:blockNum}) + let moniker = desc[0] + console.log(consensusAddr, moniker) + return moniker +} + async function getSlashCount() { let blockNum = ethers.getNumber(program.blockNum) if (blockNum === 0) { @@ -234,28 +283,20 @@ async function getSlashCount() { let totalSlash = 0 for (let i = 0; i < data[0].length; i++) { let addr = data[0][i]; - var val - if (!validatorMap.has(addr)) { - let opAddr = await stakeHub.consensusToOperator(addr, {blockTag:blockNum}) - let value = await stakeHub.getValidatorDescription(opAddr, {blockTag:blockNum}) - val = value[0] - console.log(addr, val) - } else { - val = validatorMap.get(addr) - } + var moniker = await getValidatorMoniker(addr, blockNum) let info = await slashIndicator.getSlashIndicator(addr, {blockTag:blockNum}) let count = ethers.toNumber(info[1]) totalSlash += count - console.log("Slash:", count, addr, val) + console.log("Slash:", count, addr, moniker) } console.log("Total slash count", totalSlash) }; -// 5.cmd: "GetPerformanceData", usage: -// node getchainstatus.js GetPerformanceData \ +// 5.cmd: "getPerformanceData", usage: +// node getchainstatus.js getPerformanceData \ // --rpc https://bsc-testnet-dataseed.bnbchain.org \ // --startNum 40000001 --endNum 40000005 -async function GetPerformanceData() { +async function getPerformanceData() { let txCountTotal = 0; let gasUsedTotal = 0; let inturnBlocks = 0; @@ -323,7 +364,7 @@ async function GetPerformanceData() { // --startNum 40000001 --endNum 40000005 // depends on ethjs v6.11.0+ for 4844, https://github.com/ethers-io/ethers.js/releases/tag/v6.11.0 // BSC testnet enabled 4844 on block: 39539137 -async function GetBlobTxs() { +async function getBlobTxs() { var startBlock = parseInt(program.startNum) var endBlock = parseInt(program.endNum) if (isNaN(endBlock) || isNaN(startBlock) || startBlock == 0) { @@ -359,7 +400,7 @@ async function GetBlobTxs() { // node getchainstatus.js GetFaucetStatus \ // --rpc https://bsc-testnet-dataseed.bnbchain.org \ // --startNum 40000001 --endNum 40000005 -async function GetFaucetStatus() { +async function getFaucetStatus() { var startBlock = parseInt(program.startNum) var endBlock = parseInt(program.endNum) if (isNaN(endBlock) || isNaN(startBlock) || startBlock == 0) { @@ -390,6 +431,51 @@ async function GetFaucetStatus() { console.log("successful faucet request: ",numFaucetRequest); }; + +// 8.cmd: "GetKeyParameters", usage: +// node getchainstatus.js GetKeyParameters \ +// --rpc https://bsc-testnet-dataseed.bnbchain.org \ +// --blockNum(optional): the block num which is based for the slash state, default: latest block +async function getKeyParameters() { + let blockNum = ethers.getNumber(program.blockNum) + if (blockNum === 0) { + blockNum = await provider.getBlockNumber() + } + let block = await provider.getBlock(blockNum) + console.log("At block", blockNum, "time", block.date) + + // part 1: validatorset + let numOfCabinets = await validatorSet.numOfCabinets({blockTag:blockNum}) + if (numOfCabinets == 0) { numOfCabinets = 21 } + // let maxNumOfCandidates = await validatorSet.maxNumOfCandidates({blockTag:blockNum}) // deprecated + // let turnLength = await validatorSet.turnLength({blockTag:blockNum}) + let maxNumOfWorkingCandidates = await validatorSet.maxNumOfWorkingCandidates({blockTag:blockNum}) + let maintainSlashScale = await validatorSet.maintainSlashScale({blockTag:blockNum}) + console.log("numOfCabinets", Number(numOfCabinets), "maxNumOfWorkingCandidates", Number(maxNumOfWorkingCandidates), + "maintainSlashScale", maintainSlashScale) + + // part 2: staking + // let minSelfDelegationBNB = await stakeHub.minSelfDelegationBNB({blockTag:blockNum})/BigInt(10**18) + let maxElectedValidators = await stakeHub.maxElectedValidators({blockTag:blockNum}) + let validatorElectionInfo = await stakeHub.getValidatorElectionInfo(0,0,{blockTag:blockNum}) + let consensusAddrs = validatorElectionInfo[0] + let votingPowers = validatorElectionInfo[1] + let voteAddrs = validatorElectionInfo[2] + let totalLength = validatorElectionInfo[3] + console.log("maxElectedValidators", Number(maxElectedValidators), "Registered", Number(totalLength)) + let validatorTable = [] + for (let i = 0; i < totalLength; i++) { + validatorTable.push({ + addr: consensusAddrs[i], + votingPower: Number(votingPowers[i]/BigInt(10**18)), + voteAddr: voteAddrs[i], + moniker: await getValidatorMoniker(consensusAddrs[i], blockNum) + }) + } + validatorTable.sort((a, b) => b.votingPower - a.votingPower); + console.table(validatorTable) +}; + const main = async () => { if (process.argv.length <= 2) { console.error('invalid process.argv.length', process.argv.length); @@ -401,20 +487,22 @@ const main = async () => { printUsage() return } - if (cmd === "GetTxCount") { - await getTxCount() - } else if (cmd === "GetVersion") { + if (cmd === "GetMaxTxCountInBlockRange") { + await getMaxTxCountInBlockRange() + } else if (cmd === "GetBinaryVersion") { await getBinaryVersion() } else if (cmd === "GetTopAddr") { await getTopAddr() } else if (cmd === "GetSlashCount") { await getSlashCount() } else if (cmd === "GetPerformanceData") { - await GetPerformanceData() + await getPerformanceData() } else if (cmd === "GetBlobTxs") { - await GetBlobTxs() + await getBlobTxs() } else if (cmd === "GetFaucetStatus") { - await GetFaucetStatus() + await getFaucetStatus() + } else if (cmd === "GetKeyParameters") { + await getKeyParameters() } else { console.log("unsupported cmd", cmd); printUsage()