阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

    教程列表

    数据库
    抓包专区
    测试专区

    EOS 的最高 TPS 作假

    最近看到 BM 说要搞银河系通用货币,TPS 可以打到千万!

    感觉这家伙牛逼吹的越来越狠了。

    记得以前 EOS 说是要到百万,最终线上 TPS 最高才 3000;

    而且这个数据也是作假的,估计弄高 TPS 的数据,多亏 github 上托管的,可以穿梭到当时的版本

    最开始的仓库:

    https://github.com/CryptoLions/EOS-Network-monitor

    在这个仓库里可以看到耍赖的 TPS 算法;

    文件是EOS-Network-monitor/netmon-backend/src/routines/handleBlock/findMaxInfo.js

    现在 EOS 这个项目切换为两个项目了,新项目没有这些 commit log;

    https://github.com/CryptoLions/EOS-Network-Monitor-back
    https://github.com/CryptoLions/EOS-Network-Monitor-front
    

    而且新代码也是耍赖算法的

    老代码的 TPS

    const getActionsCount = block => {
      if (block.transactions.length < 1) {
        return 0;
      }
      return block.transactions.reduce(
        (result, transaction) => result + (transaction.trx.transaction ? transaction.trx.transaction.actions.length : 0),
        0,
      );
    };
    
    const findMaxInfo = ({ current = { transactions: [] }, previous = {}, max_tps = 0, max_aps = 0 }) => {
      const SECOND = 1000;
      const currentTs = Date.parse(current.timestamp);
      const previousTs = Date.parse(previous.timestamp);
      if (currentTs === previousTs) {
        return undefined;
      }
      let live_tps;
      let live_aps;
      if (currentTs - previousTs >= SECOND) {
        live_tps = current.transactions.length;
        live_aps = getActionsCount(current);
      } else {
        live_tps = current.transactions.length + (previous.transactions ? previous.transactions.length : 0);
        live_aps = getActionsCount(current) + (previous.transactions ? getActionsCount(previous) : 0);
      }
    
      const res = {};
      if (live_tps > max_tps) {
        res.max_tps = live_tps;
        res.max_tps_block = current.block_num;
      }
      if (live_aps > max_aps) {
        res.max_aps = live_aps;
        res.max_aps_block = current.block_num;
      }
      if (res.max_aps || res.max_tps) {
        return res;
      }
      return undefined;
    };
    
    module.exports = findMaxInfo;
    

    新代码 TPS

    /* eslint-disable no-param-reassign */
    const getActionsCount = require('./getActionsCount');
    const { createEosApi } = require('../../helpers');
    const { SECOND } = require('../../constants');
    
    const eosApi = createEosApi();
    
    const findMaxInfo = async ({ current = { transactions: [] }, previous, max_tps = 0, max_aps = 0 }) => {
      if (!previous || !previous.block_num) {
        previous = await eosApi.getBlock(current.block_num - 1);
      }
      const currentTs = Date.parse(current.timestamp);
      const previousTs = Date.parse(previous.timestamp);
      if (currentTs === previousTs) {
        return undefined;
      }
      let live_tps;
      let live_aps;
      // the block was produced in one second or more
      if (currentTs - previousTs >= SECOND) {
        const transactionsNumber = current.transactions.length;
        const actionsNumber = getActionsCount(current);
        const producedInSeconds = (currentTs - previousTs) / SECOND;
        live_tps = transactionsNumber / producedInSeconds;
        live_aps = actionsNumber / producedInSeconds;
      } else {
        // the block was produced in half of second
        // find number of transactions for 0.5 sec for previous block
        if (!previous.producedInSeconds) {
          const beforePrevious = await eosApi.getBlock(previous.block_num - 1);
          previous.producedInSeconds = (Date.parse(previous.timestamp) - Date.parse(beforePrevious.timestamp)) / SECOND;
        }
        const previousTransactionsNumber = current.transactions.length;
    
        live_tps = current.transactions.length + (previousTransactionsNumber / previous.producedInSeconds / 2);
        live_aps = getActionsCount(current) + (getActionsCount(previous) / previous.producedInSeconds / 2);
      }
      live_aps = live_aps < live_tps ? live_tps : live_aps;
      const res = {};
      if (live_tps > max_tps) {
        res.max_tps = live_tps;
        res.max_tps_block = current.block_num;
      }
      if (live_aps > max_aps) {
        res.max_aps_block = current.block_num;
        res.max_aps = live_aps;
      }
      if (res.max_aps || res.max_tps) {
        return res;
      }
      return undefined;
    };
    
    module.exports = findMaxInfo;
    

    老代码的 TPS 核心计算是

    //判断当前块与上一个块的出块时间差值,
     if (currentTs - previousTs >= SECOND) {
         //如果大于等于1秒,执行这里
         //假如 块1000 与 块999 出块时间差值为6s,块1000里有3000笔交易,那么TPS取值是3000了,(而不是取3000/6),这明显是不要脸的算法
        live_tps = current.transactions.length;
      } else {
          //如果小于1s执行这里
          //假设块1001与块1000差值是0.5秒,假设块1001里有2000笔交易,块1000里有3000笔交易,那么取值是2000+3000=5000的TPS;(这个算法也是不合理)
        live_tps = current.transactions.length + (previous.transactions ? previous.transactions.length : 0);
      }
    
      const res = {};
      //以下代码是是:如果当前1001块计算出的TPS结果5000大于数据库储存的曾经最大TPS,则储存5000为最大Tps,如果不大于曾经储存的TPS,就不会更新
      if (live_tps > max_tps) {
        res.max_tps = live_tps;
        res.max_tps_block = current.block_num;
      }
      if (res.max_aps || res.max_tps) {
        return res;
      }
      return undefined;
    

    新版代码的 TPS 计算核心

      if (currentTs - previousTs >= SECOND) {
        const transactionsNumber = current.transactions.length;
        const producedInSeconds = (currentTs - previousTs) / SECOND;
        //这个的新算法已经改正了,假如 块1000 与 块999 出块时间差值为6s,块1000里有3000笔交易,那么TPS取值是 3000/6 了
        live_tps = transactionsNumber / producedInSeconds;
      } else {
        // the block was produced in half of second
        // find number of transactions for 0.5 sec for previous block
        if (!previous.producedInSeconds) {
          const beforePrevious = await eosApi.getBlock(previous.block_num - 1);
          previous.producedInSeconds = (Date.parse(previous.timestamp) - Date.parse(beforePrevious.timestamp)) / SECOND;
        }
        const previousTransactionsNumber = current.transactions.length;
        //这里取值是 (当前的Block里面的交易数量)+(上一个块交易数量/(上一个时间戳-上上的时间戳 等到的秒数)/2)
        live_tps = current.transactions.length + (previousTransactionsNumber / previous.producedInSeconds / 2);
      }
    

    新版算法里,大于 1s 的算法很合理,但是小与 1 秒的算法还是不合理,这种算法得到的结果是范围波动太大;会偏离实际值更大或者更小;

    算法 DEMO 演算,演示跑 100 个块得到的结果

    let MAX = 1500,
        MIN = 500;
    let target = [];
    for (let k=0;k<100;k++){
        let database=[];
        let temp;//临时数据
        let timeFlag=0;
        for (let i=0;i<6;i++){
            temp={
                timestamp : Math.floor(Math.random()*(MAX-MIN)+MIN)+timeFlag,
                transaction_num: 100
            };
            timeFlag = temp.timestamp;
            database.push(temp);
        }
        // console.log(database);
        let C = database[database.length-1];
        let B = database[database.length-2];
        let A = database[database.length-3];
        let liveTps1;
        let liveTps2;
        let Diff = C.timestamp - B.timestamp;
        if(Diff>=1000){
    
        }else{
            let tempDiff  = (B.timestamp - A.timestamp)/1000;
            liveTps1 = C.transaction_num + (C.transaction_num/ tempDiff / 2);
            liveTps2 = C.transaction_num / (Diff /1000);
        }
    
    
        let tempTarget={
            eos : liveTps1,
            czr: liveTps2
        };
        target.push(tempTarget);
    }
    
    console.log(target);
    let EOSMAX=0,
        EOSMIN=10000;
    let CZRMAX=0,
        CZRMIN=10000;
    target.forEach(item=>{
        //取最大TPS 取最小TPS
        if(item.eos>=EOSMAX){
            EOSMAX = item.eos;
        }
        if(item.eos<=EOSMIN){
            EOSMIN = item.eos;
        }
    
        //CZR
        if(item.czr>=CZRMAX){
            CZRMAX = item.eos;
        }
        if(item.czr<=CZRMIN){
            CZRMIN = item.eos;
        }
    });
    console.log(`EOSMAX:${EOSMAX},EOSMIN:${EOSMIN}`);
    console.log(`CZRMAX:${CZRMAX},CZRMIN:${CZRMIN}`);
    

    算法的总结

    这种算法得到的结果是范围波动太大;会偏离实际值更大或者更小;(就是波峰会高很多,波谷会低很多,精确度非常差)

    但是 EOS 是只统计曾经出现的最高值,所以这个算法是有利于统计最高 TPS 值的;

    卖前端学习教程

    只需几十元,就能买到培训班的内部教程!开启高薪之路!

    零基础小白阿里P7的教程都有!

    同时长期收购所有培训班的前端教程

    目录
    目录