use of org.aion.zero.impl.types.BlockHeader in project aion by aionnetwork.
the class AionBlockchainImpl method createNewMiningBlockInternal.
BlockContext createNewMiningBlockInternal(Block parent, List<AionTransaction> txs, boolean waitUntilBlockTime, long currTimeSeconds) {
BlockHeader parentHdr = parent.getHeader();
long time = currTimeSeconds;
if (parentHdr.getTimestamp() >= time) {
time = parentHdr.getTimestamp() + 1;
while (waitUntilBlockTime && TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) <= time) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
break;
}
}
}
long energyLimit = this.energyLimitStrategy.getEnergyLimit(parentHdr);
MiningBlock block;
try {
MiningBlockHeader.Builder headerBuilder = MiningBlockHeader.Builder.newInstance().withParentHash(parent.getHash()).withCoinbase(minerCoinbase).withNumber(parentHdr.getNumber() + 1).withTimestamp(time).withExtraData(minerExtraData).withTxTrieRoot(calcTxTrieRoot(txs)).withEnergyLimit(energyLimit).withDefaultStateRoot().withDefaultReceiptTrieRoot().withDefaultLogsBloom().withDefaultDifficulty().withDefaultNonce().withDefaultSolution();
block = new MiningBlock(headerBuilder.build(), txs);
} catch (Exception e) {
LOG.error("Construct new mining block header exception:", e);
return null;
}
BlockHeader parentMiningBlock;
BlockHeader parentMiningBlocksParent = null;
byte[] newDiff;
IDifficultyCalculator diffCalculator;
// so we use a strict greater than here
if (forkUtility.isUnityForkActive(block.getNumber())) {
if (parentHdr.getSealType() == Seal.PROOF_OF_WORK) {
LOG.warn("Tried to create 2 PoW blocks in a row");
return null;
} else {
Block[] blockFamily = repository.getBlockStore().getTwoGenerationBlocksByHashWithInfo(parentHdr.getParentHash());
Objects.requireNonNull(blockFamily[0]);
parentMiningBlock = blockFamily[0].getHeader();
parentMiningBlocksParent = blockFamily[1].getHeader();
diffCalculator = chainConfiguration.getUnityDifficultyCalculator();
}
} else {
parentMiningBlock = parentHdr;
if (!parentMiningBlock.isGenesis()) {
parentMiningBlocksParent = getParent(parentMiningBlock).getHeader();
}
diffCalculator = chainConfiguration.getPreUnityDifficultyCalculator();
}
newDiff = ByteUtil.bigIntegerToBytes(diffCalculator.calculateDifficulty(parentMiningBlock, parentMiningBlocksParent), DIFFICULTY_BYTES);
block.updateHeaderDifficulty(newDiff);
BigInteger totalTransactionFee = blockPreSeal(parentHdr, block);
if (totalTransactionFee == null) {
return null;
}
// derive base block reward
BigInteger baseBlockReward;
if (forkUtility.isSignatureSwapForkActive(block.getNumber())) {
baseBlockReward = TimeVaryingRewardsCalculator.calculateReward(block.getTimestamp() - parentHdr.getTimestamp());
} else {
baseBlockReward = this.chainConfiguration.getRewardsCalculatorBeforeSignatureSchemeSwap(forkUtility.isUnityForkActive(block.getNumber())).calculateReward(block.getNumber());
}
return new BlockContext(block, baseBlockReward, totalTransactionFee);
}
use of org.aion.zero.impl.types.BlockHeader in project aion by aionnetwork.
the class TaskValidateAndAddBlocks method run.
@Override
public void run() {
// TODO: re-evaluate priority when full functionality is implemented
Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
Block firstBlock = response.getBlocks().get(0);
Thread.currentThread().setName("check-" + displayId + "-" + firstBlock.getShortHash());
// log start of operation
if (log.isDebugEnabled()) {
log.debug("Starting block validation from peer={}, start-block={}, batch-size={}.", displayId, firstBlock.getShortHash(), response.getBlocks().size());
}
List<Block> filtered = new ArrayList<>();
List<ByteArrayWrapper> batchHashes = new ArrayList<>();
BlockHeader currentHeader, previousHeader = null;
for (Block currentBlock : response.getBlocks()) {
ByteArrayWrapper hash = currentBlock.getHashWrapper();
if (// exclude imported
importedBlockHashes.containsKey(hash) || receivedBlockHashes.containsKey(hash)) {
// exclude known hashes
previousHeader = currentBlock.getHeader();
continue;
}
currentHeader = currentBlock.getHeader();
// TODO: we could do partial evaluations here (as per fast sync specs)
if (!this.blockHeaderValidator.validate(currentHeader, log)) {
if (log.isDebugEnabled()) {
log.debug("<invalid-header num={} hash={} from peer={}/{}>", currentHeader.getNumber(), currentHeader.getHash(), displayId, peerId);
}
if (log.isTraceEnabled()) {
log.debug("<invalid-header: {}>", currentHeader.toString());
}
return;
}
// ignore batch if not ordered correctly
if (previousHeader != null && (currentHeader.getNumber() != (previousHeader.getNumber() - 1) || !Arrays.equals(previousHeader.getParentHash(), currentHeader.getHash()))) {
log.debug("<inconsistent-block-headers num={}, prev-1={}, p_hash={}, prev={} from peer={}/{}>", currentHeader.getNumber(), previousHeader.getNumber() - 1, ByteUtil.toHexString(previousHeader.getParentHash()), ByteUtil.toHexString(currentHeader.getHash()), displayId, peerId);
return;
}
filtered.add(currentBlock);
previousHeader = currentHeader;
batchHashes.add(hash);
}
if (!filtered.isEmpty()) {
ByteArrayWrapper first = batchHashes.get(0);
downloadedBlocks.offer(new BlocksWrapper(peerId, displayId, filtered));
batchHashes.forEach(k -> receivedBlockHashes.put(k, first));
}
// log end of operation
if (log.isDebugEnabled()) {
log.debug("Completed block validation from peer={}, start-block={}, batch-size={} with filtered-size={}.", displayId, firstBlock.getShortHash(), response.getBlocks().size(), filtered.size());
}
}
use of org.aion.zero.impl.types.BlockHeader in project aion by aionnetwork.
the class ReqBlocksHeadersHandler method receive.
@Override
public void receive(int _nodeIdHashcode, String _displayId, final byte[] _msgBytes) {
if (isSyncOnlyNode) {
return;
}
ReqBlocksHeaders reqHeaders = ReqBlocksHeaders.decode(_msgBytes);
if (reqHeaders != null) {
long fromBlock = reqHeaders.getFromBlock();
int take = reqHeaders.getTake();
if (log.isDebugEnabled()) {
this.log.debug("<req-headers from-number={} size={} node={}>", fromBlock, take, _displayId);
}
List<BlockHeader> headers = this.blockchain.getListOfHeadersStartFrom(fromBlock, Math.min(take, MAX_NUM_OF_BLOCKS));
ResBlocksHeaders rbhs = new ResBlocksHeaders(headers);
this.p2pMgr.send(_nodeIdHashcode, _displayId, rbhs);
} else {
this.log.error("<req-headers decode-error msg-bytes={} node={}>", _msgBytes == null ? 0 : _msgBytes.length, _nodeIdHashcode);
}
}
use of org.aion.zero.impl.types.BlockHeader in project aion by aionnetwork.
the class SyncMgr method validateAndAddBlocks.
/**
* @param _nodeIdHashcode int
* @param _displayId String
* @param _bodies List<byte[]> Assemble and validate blocks batch and add batch to import queue
* from network response blocks bodies
*/
public void validateAndAddBlocks(int _nodeIdHashcode, String _displayId, final List<SharedRLPList> _bodies) {
if (_bodies == null)
return;
log.debug("<received-bodies size={} node={}>", _bodies.size(), _displayId);
// the requests are made such that the size varies to better map headers to bodies
ByteArrayWrapper firstNodeRoot = ByteArrayWrapper.wrap(BlockUtil.getTxTrieRootFromUnsafeSource(_bodies.get(0)));
List<BlockHeader> headers = syncHeaderRequestManager.matchAndDropHeaders(_nodeIdHashcode, _bodies.size(), firstNodeRoot);
if (headers == null) {
log.debug("<assemble-and-validate-blocks could not match headers for node={} size={} txTrieRoot={}>", _displayId, _bodies.size(), firstNodeRoot);
return;
}
// assemble batch
List<Block> blocks = new ArrayList<>(_bodies.size());
Iterator<BlockHeader> headerIt = headers.iterator();
Iterator<SharedRLPList> bodyIt = _bodies.iterator();
while (headerIt.hasNext() && bodyIt.hasNext()) {
Block block = BlockUtil.newBlockWithHeaderFromUnsafeSource(headerIt.next(), (SharedRLPList) bodyIt.next().get(0));
if (block == null) {
log.debug("<assemble-and-validate-blocks node={} size={}>", _displayId, _bodies.size());
break;
} else {
blocks.add(block);
}
}
int m = blocks.size();
if (m == 0) {
return;
}
log.debug("<assembled-blocks from={} size={} node={}>", blocks.get(0).getNumber(), blocks.size(), _displayId);
// add batch
syncExecutors.execute(() -> filterBlocks(new BlocksWrapper(_nodeIdHashcode, _displayId, blocks)));
}
use of org.aion.zero.impl.types.BlockHeader in project aion by aionnetwork.
the class ResBlocksHeaders method decode.
public static ResBlocksHeaders decode(final byte[] _msgBytes, Logger logger) {
if (_msgBytes == null || _msgBytes.length == 0)
return null;
else {
try {
SharedRLPList list = (SharedRLPList) RLP.decode2SharedList(_msgBytes).get(0);
List<BlockHeader> blockHeaders = new ArrayList<>();
for (RLPElement aList : list) {
blockHeaders.add(BlockUtil.newHeaderFromUnsafeSource((SharedRLPList) aList));
}
return new ResBlocksHeaders(blockHeaders);
} catch (Exception ex) {
if (logger != null) {
logger.debug("ResBlocksHeaders decode failed!", ex);
}
return null;
}
}
}
Aggregations