use of com.jd.blockchain.consensus.raft.consensus.Block in project jdchain-core by blockchain-jd-com.
the class BlockCommitService method commitBlock.
public boolean commitBlock(Block block, BlockClosure done) throws BlockCommittedException {
boolean result = true;
long latestBlockHeight = ledgerRepository.retrieveLatestBlockHeight();
if (latestBlockHeight >= block.getHeight()) {
throw new BlockCommittedException(block.getHeight());
}
if (latestBlockHeight + 1 != block.getHeight()) {
notifyCatchUp(block.getHeight());
LOGGER.error("commit block ignore. expect height:{}, latest block: {}", block.getHeight(), latestBlockHeight);
return false;
}
RaftConsensusMessageContext context = RaftConsensusMessageContext.createContext(realmName);
context.setTimestamp(block.getProposalTimestamp());
String batch = messageHandle.beginBatch(context);
context.setBatchId(batch);
LoggerUtils.debugIfEnabled(LOGGER, "commit block start, batchId: {}", batch);
Status status = Status.OK();
try {
int msgId = 0;
for (byte[] tx : block.getTxs()) {
AsyncFuture<byte[]> asyncFuture = messageHandle.processOrdered(msgId++, tx, context);
Optional.ofNullable(done).ifPresent(d -> d.addFuture(asyncFuture));
}
messageHandle.completeBatch(context);
// todo ?
messageHandle.commitBatch(context);
LedgerBlock repositoryLatestBlock = ledgerRepository.getLatestBlock();
assert repositoryLatestBlock.getHeight() == block.getHeight();
block.setPreBlockHash(repositoryLatestBlock.getPreviousHash());
block.setCurrentBlockHash(repositoryLatestBlock.getHash());
blockCommitCallbackList.forEach(c -> c.commitCallBack(block, true));
} catch (Exception e) {
LOGGER.error("commitBlock error", e);
result = false;
messageHandle.rollbackBatch(TransactionState.CONSENSUS_ERROR.CODE, context);
status = new Status(TransactionState.CONSENSUS_ERROR.CODE, e.getMessage());
blockCommitCallbackList.forEach(c -> c.commitCallBack(block, false));
}
LoggerUtils.debugIfEnabled(LOGGER, "commit block end, batchId: {}, blockHeight: {}, status: {}", batch, block.getHeight(), status);
if (done != null) {
done.run(status);
}
return result;
}
use of com.jd.blockchain.consensus.raft.consensus.Block in project jdchain-core by blockchain-jd-com.
the class RaftNodeServerServiceImpl method proposalBlock.
private void proposalBlock(List<SubmitTx> submitTxList) {
if (!proposer.canPropose()) {
LoggerUtils.debugIfEnabled(LOGGER, "node {} can't propose block", nodeServer.getNode().getNodeId());
for (SubmitTx submitTx : submitTxList) {
submitTx.getDone().run(new Status(RaftError.ENEWLEADER, "node {} can't propose block", nodeServer.getNode().getNodeId()));
}
return;
}
LoggerUtils.debugIfEnabled(LOGGER, "node: {} begin proposal block, proposal tx size: {}", nodeServer.getNode().getNodeId(), submitTxList.size());
List<byte[]> txList = submitTxList.stream().map(SubmitTx::getValues).collect(Collectors.toList());
List<Closure> doneList = submitTxList.stream().map(SubmitTx::getDone).collect(Collectors.toList());
try {
final Task task = new Task();
Block block = proposer.proposeBlock(txList);
task.setData(ByteBuffer.wrap(serializer.serialize(block)));
task.setDone(new BlockClosure(block, doneList));
nodeServer.getNode().apply(task);
} catch (Exception e) {
LOGGER.error("proposal block error", e);
// todo retry ?
for (Closure closure : doneList) {
runSubmitTxClosure(closure, i -> RpcResponse.fail(RaftError.UNKNOWN.getNumber(), e.getMessage()), 0);
}
}
}
use of com.jd.blockchain.consensus.raft.consensus.Block in project jdchain-core by blockchain-jd-com.
the class BlockProposerService method commitCallBack.
@Override
public void commitCallBack(Block block, boolean isCommit) {
lock.lock();
try {
proposalBlockMap.headMap(block.getHeight(), true).clear();
long nextHeight = block.getHeight() + 1;
Block blockCache = proposalBlockMap.get(nextHeight);
if (isCommit) {
Optional.ofNullable(blockCache).ifPresent(b -> b.setPreBlockHash(block.getCurrentBlockHash()));
} else {
Optional.ofNullable(blockCache).ifPresent(b -> b.setPreBlockHash(block.getPreBlockHash()));
TreeMap<Long, Block> blockTreeMap = new TreeMap<>();
proposalBlockMap.values().forEach(b -> {
b.setHeight(b.getHeight() - 1);
blockTreeMap.put(b.getHeight(), b);
});
proposalBlockMap.clear();
proposalBlockMap = null;
proposalBlockMap = blockTreeMap;
}
} finally {
lock.unlock();
}
}
use of com.jd.blockchain.consensus.raft.consensus.Block in project jdchain-core by blockchain-jd-com.
the class BlockProposerService method proposeBlock.
@Override
public Block proposeBlock(List<byte[]> txs) {
lock.lock();
Block proposeBlock = new Block();
try {
proposeBlock.setProposalTimestamp(System.currentTimeMillis());
proposeBlock.setTxs(txs);
// todo: 使用latestProposalBlock减少账本查询
if (proposalBlockMap.isEmpty()) {
LedgerBlock latestBlock = ledgerRepository.retrieveLatestBlock();
proposeBlock.setPreBlockHash(latestBlock.getHash());
proposeBlock.setHeight(latestBlock.getHeight() + 1);
} else {
proposeBlock.setHeight(latestProposalBlock.getHeight() + +1);
}
proposalBlockMap.put(proposeBlock.getHeight(), proposeBlock);
latestProposalBlock = proposeBlock;
LoggerUtils.debugIfEnabled(LOGGER, "proposal cache size: {}, latest proposal height: {}", proposalBlockMap.size(), latestProposalBlock.getHeight());
} finally {
lock.unlock();
}
return proposeBlock;
}
use of com.jd.blockchain.consensus.raft.consensus.Block in project jdchain-core by blockchain-jd-com.
the class SimpleBlockSerializerServiceTest method testSerialize.
public void testSerialize() {
Block block = blockProposer.proposeBlock(Lists.newArrayList(new byte[] { 1, 2 }));
byte[] serialize = blockSerializer.serialize(block);
Block block1 = blockSerializer.deserialize(serialize);
Assert.assertEquals(block.getPreBlockHash(), block1.getPreBlockHash());
}
Aggregations