tron-节点-witness加载过程

2023-10-23 14:53:34 浏览数 (1)

简述

witness 即在tron链中就是产块节点的代名词,一般称为SR。 一般节点不产块,要配置成witness,需要启动时指定私钥,并使用--witness-w指定成为产块节点。

witness 加载过程

有两种加载方式:

  1. 参数或配置文件
  2. 指定localwitness启动

参数或配置文件

通过参数指定为witness节点,但是私钥建议写在配置文件中,否则ps查看一下进程就能看到启动参数,就全暴露了,但是如果有人能上机器,也能查看配置文件。

代码语言:javascript复制
java -jar FullNode.jar --witness -p xxxxxxxxxxxxxxxxxx

输入上面的命令后,节点就会以SR类型启动,具体是如何加载的,调用栈如下:

代码语言:javascript复制
FullNode.main()
--Args.setParam(args, Constant.TESTNET_CONF);        //381
   --PARAMETER.privateKey          //优先加载 参数
   --Constant.LOCAL_WITNESS        //或加载 配置文件
   --LocalWitnesses.setPrivateKeys //或从 keystore 中加载
FullNode.startup()
--ConsensusService.start()   // 加载localwitness

Args.setParam 加载过程

代码语言:javascript复制
@Slf4j(topic = "app")
@NoArgsConstructor
@Component
public class Args extends CommonParameter {

  @Getter
  @Setter
  private static LocalWitnesses localWitnesses = new LocalWitnesses();


  public static void setParam(final String[] args, final String confFileName) {
    // 省略部分代码
    ...
    // PARAMETER.privateKey 即 -p 或 --private-key 参数
    if (StringUtils.isNoneBlank(PARAMETER.privateKey)) {
      localWitnesses = (new LocalWitnesses(PARAMETER.privateKey));
      if (StringUtils.isNoneBlank(PARAMETER.witnessAddress)) {
        byte[] bytes = Commons.decodeFromBase58Check(PARAMETER.witnessAddress);
        if (bytes != null) {
          localWitnesses.setWitnessAccountAddress(bytes);
          logger.debug("Got localWitnessAccountAddress from cmd");
        } else {
          PARAMETER.witnessAddress = "";
          logger.warn(IGNORE_WRONG_WITNESS_ADDRESS_FORMAT);
        }
      }
      // 初始化 witness
      localWitnesses.initWitnessAccountAddress(PARAMETER.isECKeyCryptoEngine());
      logger.debug("Got privateKey from cmd");
    } else if (config.hasPath(Constant.LOCAL_WITNESS)) {
      // Constant.LOCAL_WITNESS 即,配置文件中的 localwitness 这个配置项,可以配置多个
      // 作用就是一个 java-tron 服务,配置多个witness产块,这样做的话,要约成本,一台机器就可以配置多个
      localWitnesses = new LocalWitnesses();
      List<String> localwitness = config.getStringList(Constant.LOCAL_WITNESS);
      localWitnesses.setPrivateKeys(localwitness);
      witnessAddressCheck(config);
      localWitnesses.initWitnessAccountAddress(PARAMETER.isECKeyCryptoEngine());
      logger.debug("Got privateKey from config.conf");
    } else if (config.hasPath(Constant.LOCAL_WITNESS_KEYSTORE)) {
      // 通过 keystore 加载
      localWitnesses = new LocalWitnesses();
      List<String> privateKeys = new ArrayList<String>();
      if (PARAMETER.isWitness()) {
        List<String> localwitness = config.getStringList(Constant.LOCAL_WITNESS_KEYSTORE);
        if (localwitness.size() > 0) {
          String fileName = System.getProperty("user.dir")   "/"   localwitness.get(0);
          String password;
          if (StringUtils.isEmpty(PARAMETER.password)) {
            System.out.println("Please input your password.");
            password = WalletUtils.inputPassword();
          } else {
            password = PARAMETER.password;
            PARAMETER.password = null;
          }

          try {
            Credentials credentials = WalletUtils
                .loadCredentials(password, new File(fileName));
            SignInterface sign = credentials.getSignInterface();
            String prikey = ByteArray.toHexString(sign.getPrivateKey());
            privateKeys.add(prikey);
          } catch (IOException | CipherException e) {
            logger.error(e.getMessage());
            logger.error("Witness node start failed!");
            exit(-1);
          }
        }
      }
      localWitnesses.setPrivateKeys(privateKeys);
      witnessAddressCheck(config);
      localWitnesses.initWitnessAccountAddress(PARAMETER.isECKeyCryptoEngine());
      logger.debug("Got privateKey from keystore");
    }
    // 省略部分代码
    ...
  }
}

共识阶段加载

ConsensusService 主要控制共识相关,在启动时。

代码语言:javascript复制
ConsensusService.start
--Consensus.start
   --DposService.start // 对共抽的抽象,设计上方便切换共识

几个关注的点:

  1. 设置成witness节点
  2. 加载前面的私钥
  3. 启动共识
  4. 更新updateWitness
代码语言:javascript复制
public void start() {
  Param param = Param.getInstance();
  // 设置成 witness 节点
  param.setEnable(parameter.isWitness());
  param.setGenesisBlock(parameter.getGenesisBlock());
  param.setMinParticipationRate(parameter.getMinParticipationRate());
  param.setBlockProduceTimeoutPercent(Args.getInstance().getBlockProducedTimeOut());
  param.setNeedSyncCheck(parameter.isNeedSyncCheck());
  param.setAgreeNodeCount(parameter.getAgreeNodeCount());
  List<Miner> miners = new ArrayList<>();
  // 拿到私钥列表
  List<String> privateKeys = Args.getLocalWitnesses().getPrivateKeys();
  if (privateKeys.size() > 1) {
    // 前面说了,可以配置多个 私钥,所以这里遍历
    for (String key : privateKeys) {
      byte[] privateKey = fromHexString(key);
      byte[] privateKeyAddress = SignUtils
          .fromPrivate(privateKey, Args.getInstance().isECKeyCryptoEngine()).getAddress();
      WitnessCapsule witnessCapsule = witnessStore.get(privateKeyAddress);
      if (null == witnessCapsule) {
        logger.warn("Witness {} is not in witnessStore.", Hex.toHexString(privateKeyAddress));
      }
      // 封装到 Miner 中,在产块时私钥相关校验
      Miner miner = param.new Miner(privateKey, ByteString.copyFrom(privateKeyAddress),
          ByteString.copyFrom(privateKeyAddress));
      miners.add(miner);
      logger.info("Add witness: {}, size: {}",
          Hex.toHexString(privateKeyAddress), miners.size());
    }
  } else {
    byte[] privateKey =
        fromHexString(Args.getLocalWitnesses().getPrivateKey());
    byte[] privateKeyAddress = SignUtils.fromPrivate(privateKey,
        Args.getInstance().isECKeyCryptoEngine()).getAddress();
    byte[] witnessAddress = Args.getLocalWitnesses().getWitnessAccountAddress(
        Args.getInstance().isECKeyCryptoEngine());
    WitnessCapsule witnessCapsule = witnessStore.get(witnessAddress);
    if (null == witnessCapsule) {
      logger.warn("Witness {} is not in witnessStore.", Hex.toHexString(witnessAddress));
    }
    Miner miner = param.new Miner(privateKey, ByteString.copyFrom(privateKeyAddress),
        ByteString.copyFrom(witnessAddress));
    miners.add(miner);
  }

  param.setMiners(miners);
  param.setBlockHandle(blockHandle);
  param.setPbftInterface(pbftBaseImpl);
  // 启动共识
  consensus.start(param);
  logger.info("consensus service start success");
}

Dpos 中加载

//TODO

0 人点赞