use of io.nuls.consensus.poc.model.BlockExtendsData in project nuls by nuls-io.
the class ConsensusProcess method doPacking.
private Block doPacking(MeetingMember self, MeetingRound round) throws NulsException, IOException {
Block bestBlock = chainManager.getBestBlock();
/**
********************************************************************************************************
*/
// pierre test comment out
// try {
// Log.info("");
// Log.info("****************************************************");
// Log.info("开始打包,获取当前bestblock, height:{},- {}", bestBlock.getHeader().getHeight(), bestBlock.getHeader().getHash());
// Log.info("开始打包,获取当前EndBlockHeader, height:{},- {}", chainManager.getMasterChain().getChain().getEndBlockHeader().getHeight(),
// chainManager.getMasterChain().getChain().getEndBlockHeader().getHash());
// Log.info("****************************************************");
// Log.info("");
//
// } catch (Exception e) {
// e.printStackTrace();
// }
/**
********************************************************************************************************
*/
BlockData bd = new BlockData();
bd.setHeight(bestBlock.getHeader().getHeight() + 1);
bd.setPreHash(bestBlock.getHeader().getHash());
bd.setTime(self.getPackEndTime());
BlockExtendsData extendsData = new BlockExtendsData();
extendsData.setRoundIndex(round.getIndex());
extendsData.setConsensusMemberCount(round.getMemberCount());
extendsData.setPackingIndexOfRound(self.getPackingIndexOfRound());
extendsData.setRoundStartTime(round.getStartTime());
// 添加版本升级相应协议数据
if (NulsVersionManager.getCurrentVersion() > 1) {
extendsData.setMainVersion(NulsVersionManager.getMainVersion());
extendsData.setCurrentVersion(NulsVersionManager.getCurrentVersion());
extendsData.setPercent(NulsVersionManager.getCurrentProtocolContainer().getPercent());
extendsData.setDelay(NulsVersionManager.getCurrentProtocolContainer().getDelay());
}
if (NulsVersionManager.getMainVersion() >= 3) {
RandomSeedStatusPo status = randomSeedsStorageService.getAddressStatus(self.getPackingAddress());
byte[] seed = ConsensusStorageConstant.EMPTY_SEED;
if (null != status && status.getNextSeed() != null) {
seed = status.getNextSeed();
}
extendsData.setSeed(seed);
byte[] nextSeed = RandomSeedUtils.createRandomSeed();
byte[] nextSeedHash = RandomSeedUtils.getLastDigestEightBytes(nextSeed);
extendsData.setNextSeedHash(nextSeedHash);
RandomSeedStatusPo po = new RandomSeedStatusPo();
po.setAddress(self.getPackingAddress());
// Log.info("{}====={}====={}", bd.getHeight(), Hex.encode(nextSeed), Hex.encode(nextSeedHash));
po.setSeedHash(nextSeedHash);
po.setNextSeed(nextSeed);
po.setHeight(bd.getHeight());
RandomSeedUtils.CACHE_SEED = po;
}
StringBuilder str = new StringBuilder();
str.append(AddressTool.getStringAddressByBytes(self.getPackingAddress()));
str.append(" ,order:" + self.getPackingIndexOfRound());
str.append(",packTime:" + new Date(self.getPackEndTime()));
str.append("\n");
Log.debug("pack round:" + str);
bd.setExtendsData(extendsData);
List<Transaction> packingTxList = new ArrayList<>();
Set<NulsDigestData> outHashSet = new HashSet<>();
long totalSize = 0L;
Map<String, Coin> toMaps = new HashMap<>();
Set<String> fromSet = new HashSet<>();
/**
* pierre add 智能合约相关
*/
byte[] stateRoot = ConsensusTool.getStateRoot(bestBlock.getHeader());
// 更新世界状态根
bd.setStateRoot(stateRoot);
long height = bestBlock.getHeader().getHeight();
ContractResult contractResult;
Map<String, Coin> contractUsedCoinMap = new HashMap<>();
int totalGasUsed = 0;
int count = 0;
long start = 0;
long ledgerUse = 0;
long verifyUse = 0;
long outHashSetUse = 0;
long getTxUse = 0;
long sleepTIme = 0;
long whileTime = 0;
long startWhile = System.currentTimeMillis();
long sizeTime = 0;
long failed1Use = 0;
long addTime = 0;
Block tempBlock = new Block();
BlockHeader tempHeader = new BlockHeader();
tempHeader.setTime(bd.getTime());
tempHeader.setHeight(bd.getHeight());
tempHeader.setPackingAddress(round.getLocalPacker().getAddress().getAddressBytes());
tempBlock.setHeader(tempHeader);
// 为本次打包区块增加一个合约的临时余额区,用于记录本次合约地址余额的变化
contractService.createContractTempBalance();
// 为本次打包区块创建一个批量执行合约的执行器
contractService.createBatchExecute(stateRoot);
// 为本地打包区块存储当前块的部分区块头信息(高度、时间、打包者地址)
contractService.createCurrentBlockHeader(tempHeader);
List<ContractResult> contractResultList = new ArrayList<>();
Set<String> redPunishAddress = new HashSet<>();
while (true) {
if ((self.getPackEndTime() - TimeService.currentTimeMillis()) <= 500L) {
break;
}
start = System.nanoTime();
Transaction tx = txMemoryPool.get();
getTxUse += (System.nanoTime() - start);
if (tx == null) {
try {
sleepTIme += 100;
Thread.sleep(100L);
} catch (InterruptedException e) {
Log.error("packaging error ", e);
}
continue;
}
start = System.nanoTime();
long txSize = tx.size();
sizeTime += (System.nanoTime() - start);
if ((totalSize + txSize) > ProtocolConstant.MAX_BLOCK_SIZE) {
txMemoryPool.addInFirst(tx, false);
break;
}
// 区块中可以消耗的最大Gas总量,超过这个值,则本区块中不再继续组装消耗GAS智能合约交易
if (totalGasUsed > ContractConstant.MAX_PACKAGE_GAS && ContractUtil.isGasCostContractTransaction(tx)) {
txMemoryPool.addInFirst(tx, false);
continue;
}
count++;
start = System.nanoTime();
Transaction repeatTx = ledgerService.getTx(tx.getHash());
ledgerUse += (System.nanoTime() - start);
if (repeatTx != null) {
continue;
}
ValidateResult result = ValidateResult.getSuccessResult();
if (tx.isSystemTx() && tx.getType() == ConsensusConstant.TX_TYPE_RED_PUNISH) {
RedPunishTransaction rpTx = (RedPunishTransaction) tx;
boolean con = redPunishAddress.add(AddressTool.getStringAddressByBytes(rpTx.getTxData().getAddress())) && PocConsensusContext.getChainManager().getMasterChain().getChain().getAgentByAddress(rpTx.getTxData().getAddress()) != null;
result.setSuccess(con);
} else if (tx.isSystemTx()) {
result = ValidateResult.getFailedResult(this.getClass().getSimpleName(), TransactionErrorCode.TX_NOT_EFFECTIVE);
} else {
start = System.nanoTime();
result = ledgerService.verifyCoinData(tx, toMaps, fromSet);
verifyUse += (System.nanoTime() - start);
}
start = System.nanoTime();
if (result.isFailed()) {
if (tx == null) {
continue;
}
if (result.getErrorCode().equals(TransactionErrorCode.ORPHAN_TX)) {
txMemoryPool.add(tx, true);
}
failed1Use += (System.nanoTime() - start);
continue;
}
start = System.nanoTime();
if (!outHashSet.add(tx.getHash())) {
outHashSetUse += (System.nanoTime() - start);
Log.warn("重复的交易");
continue;
}
outHashSetUse += (System.nanoTime() - start);
// 打包时发现智能合约交易就调用智能合约
if (ContractUtil.isContractTransaction(tx)) {
contractResult = contractService.batchPackageTx(tx, height, tempBlock, stateRoot, toMaps, contractUsedCoinMap).getData();
if (contractResult != null) {
totalGasUsed += contractResult.getGasUsed();
contractResultList.add(contractResult);
}
}
tx.setBlockHeight(bd.getHeight());
start = System.nanoTime();
packingTxList.add(tx);
addTime += (System.nanoTime() - start);
totalSize += txSize;
}
// 打包结束后移除临时余额区
contractService.removeContractTempBalance();
stateRoot = contractService.commitBatchExecute().getData();
// 打包结束后移除批量执行合约的执行器
contractService.removeBatchExecute();
// 打包结束后移除当前区块头信息
contractService.removeCurrentBlockHeader();
tempBlock.getHeader().setStateRoot(stateRoot);
for (ContractResult result : contractResultList) {
result.setStateRoot(stateRoot);
}
// 更新世界状态
bd.setStateRoot(stateRoot);
whileTime = System.currentTimeMillis() - startWhile;
ValidateResult validateResult = null;
int failedCount = 0;
long failedUse = 0;
start = System.nanoTime();
while (null == validateResult || validateResult.isFailed()) {
failedCount++;
validateResult = transactionService.conflictDetect(packingTxList);
if (validateResult.isFailed()) {
if (validateResult.getData() instanceof Transaction) {
packingTxList.remove(validateResult.getData());
} else if (validateResult.getData() instanceof List) {
List<Transaction> list = (List<Transaction>) validateResult.getData();
if (list.size() == 2) {
packingTxList.remove(list.get(1));
} else {
packingTxList.removeAll(list);
}
} else if (validateResult.getData() == null) {
Log.error("Cann't find the wrong transaction!");
}
}
}
// 组装CoinBase交易,另外合约调用退还剩余的Gas
failedUse = System.nanoTime() - start;
start = System.nanoTime();
addConsensusTx(bestBlock, packingTxList, self, round);
long consensusTxUse = System.nanoTime() - start;
bd.setTxList(packingTxList);
start = System.nanoTime();
// 更新本地打包最终世界状态根
bd.getExtendsData().setStateRoot(bd.getStateRoot());
Block newBlock = ConsensusTool.createBlock(bd, round.getLocalPacker());
long createBlockUser = System.nanoTime() - start;
Log.info("make block height:" + newBlock.getHeader().getHeight() + ",txCount: " + newBlock.getTxs().size() + " , block size: " + newBlock.size() + " , time:" + DateUtil.convertDate(new Date(newBlock.getHeader().getTime())) + ",packEndTime:" + DateUtil.convertDate(new Date(self.getPackEndTime())));
// pierre test comment out
Log.debug("\ncheck count:" + count + "\ngetTxUse:" + getTxUse / 1000000 + " ,\nledgerExistUse:" + ledgerUse / 1000000 + ", \nverifyUse:" + verifyUse / 1000000 + " ,\noutHashSetUse:" + outHashSetUse / 1000000 + " ,\nfailedTimes:" + failedCount + ", \nfailedUse:" + failedUse / 1000000 + " ,\nconsensusTx:" + consensusTxUse / 1000000 + ", \nblockUse:" + createBlockUser / 1000000 + ", \nsleepTIme:" + sleepTIme + ",\nwhileTime:" + whileTime + ", \naddTime:" + addTime / 1000000 + " ,\nsizeTime:" + sizeTime / 1000000 + " ,\nfailed1Use:" + failed1Use / 1000000);
return newBlock;
}
use of io.nuls.consensus.poc.model.BlockExtendsData in project nuls by nuls-io.
the class RedPunishTxProcessor method onCommit.
@Override
public Result onCommit(RedPunishTransaction tx, Object secondaryData) {
RedPunishData punishData = tx.getTxData();
BlockHeader header = (BlockHeader) secondaryData;
BlockExtendsData roundData = new BlockExtendsData(header.getExtend());
PunishLogPo punishLogPo = new PunishLogPo();
punishLogPo.setAddress(punishData.getAddress());
punishLogPo.setHeight(tx.getBlockHeight());
punishLogPo.setRoundIndex(roundData.getRoundIndex());
punishLogPo.setTime(tx.getTime());
punishLogPo.setType(PunishType.RED.getCode());
punishLogPo.setEvidence(punishData.getEvidence());
punishLogPo.setReasonCode(punishData.getReasonCode());
List<AgentPo> agentList = agentStorageService.getList();
AgentPo agent = null;
for (AgentPo agentPo : agentList) {
if (agentPo.getDelHeight() > 0) {
continue;
}
if (Arrays.equals(agentPo.getAgentAddress(), punishLogPo.getAddress())) {
agent = agentPo;
break;
}
}
if (null == agent) {
Log.error("There is no agent can be punished.");
return Result.getSuccess();
}
List<DepositPo> depositPoList = depositStorageService.getList();
List<DepositPo> updatedList = new ArrayList<>();
for (DepositPo po : depositPoList) {
if (po.getDelHeight() >= 0) {
continue;
}
if (!po.getAgentHash().equals(agent.getHash())) {
continue;
}
po.setDelHeight(tx.getBlockHeight());
boolean b = depositStorageService.save(po);
if (!b) {
for (DepositPo po2 : updatedList) {
po2.setDelHeight(-1);
this.depositStorageService.save(po2);
}
return ValidateResult.getFailedResult(this.getClass().getName(), PocConsensusErrorCode.UPDATE_DEPOSIT_FAILED);
}
updatedList.add(po);
}
boolean success = storageService.save(punishLogPo);
if (!success) {
for (DepositPo po2 : updatedList) {
po2.setDelHeight(-1);
this.depositStorageService.save(po2);
}
throw new NulsRuntimeException(TransactionErrorCode.ROLLBACK_TRANSACTION_FAILED);
}
AgentPo agentPo = agent;
agentPo.setDelHeight(tx.getBlockHeight());
success = agentStorageService.save(agentPo);
if (!success) {
for (DepositPo po2 : updatedList) {
po2.setDelHeight(-1);
this.depositStorageService.save(po2);
}
this.storageService.delete(punishLogPo.getKey());
return Result.getFailed(PocConsensusErrorCode.UPDATE_AGENT_FAILED);
}
return Result.getSuccess();
}
use of io.nuls.consensus.poc.model.BlockExtendsData in project nuls by nuls-io.
the class ForkChainProcess method clearMasterChainData.
private void clearMasterChainData() {
Chain masterChain = chainManager.getMasterChain().getChain();
long bestHeight = masterChain.getEndBlockHeader().getHeight();
List<Agent> agentList = masterChain.getAgentList();
List<Deposit> depositList = masterChain.getDepositList();
Iterator<Agent> ait = agentList.iterator();
while (ait.hasNext()) {
Agent agent = ait.next();
if (agent.getDelHeight() > 0L && (bestHeight - 1000) > agent.getDelHeight()) {
ait.remove();
}
}
Iterator<Deposit> dit = depositList.iterator();
while (dit.hasNext()) {
Deposit deposit = dit.next();
if (deposit.getDelHeight() > 0L && (bestHeight - 1000) > deposit.getDelHeight()) {
dit.remove();
}
}
BlockExtendsData roundData = new BlockExtendsData(chainManager.getBestBlock().getHeader().getExtend());
List<PunishLogPo> yellowList = masterChain.getYellowPunishList();
Iterator<PunishLogPo> yit = yellowList.iterator();
while (yit.hasNext()) {
PunishLogPo punishLog = yit.next();
if (punishLog.getRoundIndex() < roundData.getPackingIndexOfRound() - PocConsensusConstant.INIT_HEADERS_OF_ROUND_COUNT) {
yit.remove();
}
}
}
use of io.nuls.consensus.poc.model.BlockExtendsData in project nuls by nuls-io.
the class RandomSeedService method processBlock.
public void processBlock(BlockHeader header, BlockHeader preHeader) {
if (NulsVersionManager.getMainVersion() < 3) {
return;
}
BlockExtendsData extendsData = new BlockExtendsData(header.getExtend());
byte[] nextSeed = null;
if (ArraysTool.arrayEquals(header.getPackingAddress(), RandomSeedUtils.CACHE_SEED.getAddress())) {
nextSeed = RandomSeedUtils.CACHE_SEED.getNextSeed();
}
byte[] seed = extendsData.getSeed();
RandomSeedStatusPo po = this.randomSeedsStorageService.getAddressStatus(header.getPackingAddress());
long preHeight = 0;
// pierre test comment out
if (null == po || ArraysTool.arrayEquals(preHeader.getPackingAddress(), header.getPackingAddress()) || !ArraysTool.arrayEquals(RandomSeedUtils.getLastDigestEightBytes(extendsData.getSeed()), po.getSeedHash())) {
seed = ConsensusStorageConstant.EMPTY_SEED;
}
if (null != po) {
preHeight = po.getHeight();
}
randomSeedsStorageService.saveAddressStatus(header.getPackingAddress(), header.getHeight(), nextSeed, extendsData.getNextSeedHash());
randomSeedsStorageService.saveRandomSeed(header.getHeight(), preHeight, seed, extendsData.getNextSeedHash());
}
use of io.nuls.consensus.poc.model.BlockExtendsData in project nuls by nuls-io.
the class ConsensusTool method getStateRoot.
public static byte[] getStateRoot(BlockHeader blockHeader) {
if (blockHeader == null || blockHeader.getExtend() == null) {
return null;
}
byte[] stateRoot = blockHeader.getStateRoot();
if (stateRoot != null && stateRoot.length > 0) {
return stateRoot;
}
try {
BlockExtendsData extendsData = new BlockExtendsData(blockHeader.getExtend());
stateRoot = extendsData.getStateRoot();
if ((stateRoot == null || stateRoot.length == 0) && NulsContext.MAIN_NET_VERSION > 1) {
stateRoot = Hex.decode(NulsContext.INITIAL_STATE_ROOT);
}
blockHeader.setStateRoot(stateRoot);
return stateRoot;
} catch (Exception e) {
Log.error("parse stateRoot of blockHeader error.", e);
return null;
}
}
Aggregations