signum共识过程

项目集合

signum-node: https://github.com/signum-network/signum-node.git
signum-miner: https://github.com/signum-network/signum-miner.git
signum-plot:https://github.com/signum-network/signum-plotter.git
btdex: https://github.com/btdex/btdex.git

signum-node是一个全节点,存放有全部的区块信息
signum-miner实现挖矿逻辑,
btdex 是挖矿界面,会调用signum-miner实现挖矿逻辑。

class MineThread extends Thread {
	public void run() {
		try {
			String cmd = minerFile.getAbsolutePath() + " -c " + MINER_CONFIG_FILE;
			logger.info("Running miner with '{}'", cmd);
			minerProcess = Runtime.getRuntime().exec(cmd, null, minerFile.getParentFile());
			
			InputStream stdIn = minerProcess.getInputStream();
			InputStreamReader isr = new InputStreamReader(stdIn);
			BufferedReader br = new BufferedReader(isr);

			while (minerProcess.isAlive()) {
				String line = br.readLine();
				if(line != null)
					addToConsole(MINER_APP, line);
			}
			mining = false;
			minerFile.delete();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	};

btdex 调用miner下的二进制文件signum-miner,signum-miner实现具体的挖矿流程

create_cpu_worker_task->hash->find_best_deadline_rust

pub fn find_best_deadline_rust(
    data: &[u8],
    number_of_nonces: u64,
    gensig: &[u8; 32],
) -> (u64, u64) {
    let mut best_deadline = u64::MAX;
    let mut best_offset = 0;
    for i in 0..number_of_nonces as usize {
        let result =
            shabal256_deadline_fast(&data[i * SCOOP_SIZE..i * SCOOP_SIZE + SCOOP_SIZE], &gensig);
        if result < best_deadline {
            best_deadline = result;
            best_offset = i;
        }
    }
    (best_deadline, best_offset as u64)
}

plot

String plotterName = "signum-plotter";
		if(OS.isWindows())
			plotterName += ".exe";
		else if(OS.isMacOsX())
			plotterName += ".app";
		
		plotterFile = new File(TMP_DIR, plotterName);
		if (!plotterFile.exists() || plotterFile.length() == 0) {
		     InputStream link = (getClass().getResourceAsStream("/plotter/" + plotterName));
		     try {
		    	logger.info("Copying ploter to {}", plotterFile.getAbsolutePath());
				Files.copy(link, plotterFile.getAbsoluteFile().toPath());
				if(!OS.isWindows())
					plotterFile.setExecutable(true);
			} catch (IOException ex) {
				ex.printStackTrace();
				Toast.makeText((JFrame) SwingUtilities.getWindowAncestor(this), ex.getMessage(), Toast.Style.ERROR).display();
				plotting = false;
				return;
			}
		}
		
		PlotThread plotThread = new PlotThread();
		plotThread.start();

出块和共识过程

1 signum-miner扫描磁盘找到合适的nonce和deadline,向节点提交nonce

    let mut query = format!(
            "requestType=submitNonce&accountId={}&nonce={}&secretPhrase={}&blockheight={}",
            submission_data.account_id, submission_data.nonce, secret_phrase, submission_data.height
        );

        // If we don't have a secret phrase then we most likely talk to a pool or a proxy.
        // Both can make use of the deadline, e.g. a proxy won't validate deadlines but still
        // needs to rank the deadlines.
        // The best thing is that legacy proxies use the unadjusted deadlines so...
        // yay another parameter!
        if secret_phrase == "" {
            query += &format!("&deadline={}", submission_data.deadline_unadjusted);
        }        

2 节点维护了generators结合,这个集合存储使用这个节点出块的accountID,私钥,块高,这个数据结构可以根据nonce计算deadline节点收到submitNonce后,会调用addNonce方法

/src/brs/GeneratorImpl.java
 private final Long accountId;
    private final String secretPhrase;
    private final byte[] publicKey;
    private final BigInteger deadline;
    private final BigInteger hit;
    private final long baseTarget;
    private final long nonce;
    private final long block;
/src/brs/GeneratorImpl.java
  public GeneratorState addNonce(String secretPhrase, Long nonce, byte[] publicKey) {
    byte[] publicKeyHash = Crypto.sha256().digest(publicKey);
    long id = Convert.fullHashToId(publicKeyHash);

    GeneratorStateImpl generator = new GeneratorStateImpl(secretPhrase, nonce, publicKey, id);
    GeneratorStateImpl curGen = generators.get(id);
    if (curGen == null || generator.getBlock() > curGen.getBlock() || generator.getDeadline().compareTo(curGen.getDeadline()) < 0) {
      generators.put(id, generator);
      listeners.notify(generator, Event.NONCE_SUBMITTED);
      if (logger.isDebugEnabled()) {
        logger.debug("Account {} started mining, deadline {} seconds", Convert.toUnsignedLong(id), generator.getDeadline());
      }
    } else {
      if (logger.isDebugEnabled()) {
        logger.debug("Account {} already has a better nonce", Convert.toUnsignedLong(id));
      }
    }

    return generator;
  }

3 GeneratorImpl有一个定时任务,每0.5秒跑一次,使用generator出块
出块调用的方法是generator.getValue().forge(blockchainProcessor);

 private Runnable generateBlockThread(BlockchainProcessor blockchainProcessor) {
    return () -> {
      if (blockchainProcessor.isScanning()) {
        return;
      }
      try {
        long currentBlock = blockchain.getLastBlock().getHeight();
        Iterator<Entry<Long, GeneratorStateImpl>> it = generators.entrySet().iterator();
        while (it.hasNext() && !Thread.currentThread().isInterrupted() && ThreadPool.running.get()) {
          Entry<Long, GeneratorStateImpl> generator = it.next();
          if (currentBlock < generator.getValue().getBlock()) {
            generator.getValue().forge(blockchainProcessor);
          } else {
            it.remove();
          }
        }
      } catch (BlockchainProcessor.BlockNotAcceptedException e) {
        logger.debug("Error in block generation thread", e);
      }
    };
  }

4 forge方法最终调用的是BlockchainProcessor的generateBlock方法,generateBlock会调用pushBlock方法,
pushBlock会验证执行交易,并且把block推到其他peerr

出块和向其他peer推送交易

  logger.debug("Successfully pushed {} (height {})", block.getId(), block.getHeight());
  statisticsManager.blockAdded();
  blockListeners.notify(block, Event.BLOCK_PUSHED);
  if (block.getTimestamp() >= timeService.getEpochTime() - MAX_TIMESTAMP_DIFFERENCE) {
      Peers.sendToSomePeers(block);
  }

signum共识过程_第1张图片

BlockchainProcessorImpl中调度多个定时任务
getMoreBlocksThread:获取更多block
blockImporterThread:使用区块,调用verifyGenerationSignature会使用到setPocTime
pocVerificationThread:验证区块->blockService.preVerify->setPocTime

1 GeneratorImpl.calculateHit计算Scoop number

你可能感兴趣的:(区块链)