前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >tron 参与度算法模拟

tron 参与度算法模拟

作者头像
潇洒
发布2023-10-23 14:52:50
1160
发布2023-10-23 14:52:50
举报
文章被收录于专栏:石头岛石头岛

简述

这个算法是在分布式场景下,计算不同节点之前的参与度,也就是有多少节点还存活,并参与到正常的业务处理当中。

为什么需要: 参与度?

大白话就是有什么用,不用行不行? 在中心化的应用当中,网络的数据处理只需要提交易中心节点处理即可。如下一个订单、注册一个用户。 在区块链场景下,所有节点之前都是独立的个体,谁也没有比较权威,在完成一个业务的处理,需要多个节点的认可才可能完成。 用不用需要看是使用的哪一种共识协议。如果是POW完全不用考虑,如果是DPOS这种就需要。 在分布式环境下,一件事需要处理成功,需要有一定数量的可信节点来证明!证明!证明!,否则这件事就不可能被认为是一件可信的事情,比如,有一个节点给自己的账户转了1000万,并生产了一个区块记账,那这个区块必须得到网络中半数以上的验证者认可,那这个区块就是可信的。如果不需要的话,自己可以随意改代码给做对自己有利的事,那这个网络就没有人会信任,所以需要有一定的节点成为:验证者

验证者

那就选出一批验证者来干活。问题是,网络是分布式的,机器、网络节点有可能会故障挂掉,如何确保挂掉一部分验证者后,网络还能继续工作。那就需要保证有一批最小的可信验证者,就需要一个算法,来计算当前还有多少可信验证者

这里不谈为什么这些节点是否可信的问题,因为拜占庭将军问题解释起来有点多,只谈如何计算这些节点的有多少个,这个值就是:参与度

事情就是这么个事,那如何计算呢?

分析

在分布式环境中,需要指定最少多少节点参与,才可以保证节点的正常运行。那就需要指定一个最小参与度。 需要考虑几个维护:

  1. 最大参与者
  2. 最小参与度
  3. 节点挂掉后,如何降底参与度
  4. 节点恢复后,如何提升级与度

参与度的值就是通过参与者进行计出来的,那么我们需要知道一个最小的参与度minParticipationRate。 这个值可以设置一个百分比来控制。

还有一个问题,整个网络环境是去中心化的呀,我怎么能知道,邻居节点挂了,依据是什么? 这个问题好解决,在DPOS协议当中,设定了27个验证者节点,且每3秒之间就会有一次区块交互,如果3秒内我没有收到上一个节点发给我的区块,说明上一个节点可能出现问题了,那么我就记一笔,上一个节点有问题可信节点-1。 OK那么节点之间的发现问题由DPOS协议来保证。

代码语言:javascript
复制
package com.liukai.blockchain.labs;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;

import static java.util.Arrays.fill;

/**
 * @author liukai
 * @since 2022/4/25.
 */
public class BlockFilledSlot {

  public static Map<String, Object> database = new HashMap<>();

  public static final int BLOCK_FILLED_SLOTS_NUMBER = 128;

  static {
    initFill();
    initBlockFilledSlotsIndex();
  }

  public static void initFill() {
    int[] blockFilledSlots = new int[getBlockFilledSlotsNumber()];
    fill(blockFilledSlots, 1);
    database.put("BLOCK_FILLED_SLOTS", blockFilledSlots);
    System.out.println("init param");
    System.out.println("SlotCount=" + IntStream.of(blockFilledSlots).sum());
    System.out.println("Percent=" + calculateFilledSlotsCount() + "%");
    System.out.println("===================");
  }

  public static void initBlockFilledSlotsIndex() {
    database.put("BLOCK_FILLED_SLOTS_INDEX", 0);
  }

  public static int getBlockFilledSlotsIndex() {
    return (int) database.get("BLOCK_FILLED_SLOTS_INDEX");
  }

  public static int getBlockFilledSlotsNumber() {
    return BLOCK_FILLED_SLOTS_NUMBER;
  }

  public static int[] getBlockFilledSlots() {
    return (int[]) database.get("BLOCK_FILLED_SLOTS");
  }

  // 每一次 true false 都会让 index 往前或后移动一步
  public static void applyBlock(boolean fillBlock) {
    int[] blockFilledSlots = getBlockFilledSlots();
    int blockFilledSlotsIndex = getBlockFilledSlotsIndex();
//    System.out.println("blockFilledSlotsIndex before: " + blockFilledSlotsIndex);
    blockFilledSlots[blockFilledSlotsIndex] = fillBlock ? 1 : 0;
    saveBlockFilledSlots(blockFilledSlots);
    saveBlockFilledSlotsIndex((blockFilledSlotsIndex + 1) % getBlockFilledSlotsNumber());
//    System.out.println("blockFilledSlotsIndex after: " + getBlockFilledSlotsIndex());
  }

  private static void saveBlockFilledSlots(int[] blockFilledSlots) {
//    System.out.println("array: " + Arrays.toString(blockFilledSlots));
    database.put("BLOCK_FILLED_SLOTS", blockFilledSlots);
  }

  private static void saveBlockFilledSlotsIndex(int i) {
    database.put("BLOCK_FILLED_SLOTS_INDEX", i);
  }

  public static int calculateFilledSlotsCount() {
    int[] blockFilledSlots = getBlockFilledSlots();
    int sum = IntStream.of(blockFilledSlots).sum();
//    System.out.println("calculateFilledSlotsCount: " + sum);
    return 100 * sum / getBlockFilledSlotsNumber();
  }

  public static void main(String[] args) {
    int slot = 64;
    // 实际中,slot 的个数是根据 witness 的产块与否来决定的
    for (int i = 0; i < slot; i++) {
      applyBlock(false);
      System.out.println("SlotsCount: " + IntStream.of(getBlockFilledSlots()).sum());
      System.out.println("Percent: " + calculateFilledSlotsCount() + " %");
    }
    System.out.println("-----------");
    for (int i = 0; i < 128; i++) {
      applyBlock(true);
      System.out.println("SlotsCount: " + IntStream.of(getBlockFilledSlots()).sum());
      System.out.println("Percent: " + calculateFilledSlotsCount() + " %");
    }
  }
}

总结

参与度算法可以用来限制整个SR网络的产块状态,但是严格的参与度限制,也会使整个网络的产块稳定性和效率降低。 如果为了产块的稳定性,参与度并不是越大越好。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-07-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简述
    • 为什么需要: 参与度?
      • 验证者
      • 分析
      • 总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档