use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class BlockPropagationHandler method processIncomingBlock.
public PropStatus processIncomingBlock(final int nodeId, final String displayId, final Block block) {
if (block == null)
return PropStatus.DROPPED;
ByteArrayWrapper hashWrapped = block.getHashWrapper();
if (!this.blockHeaderValidator.validate(block.getHeader(), log))
return PropStatus.DROPPED;
// guarantees if multiple requests of same block appears, only one goes through
synchronized (this.cacheMap) {
if (this.cacheMap.get(hashWrapped) != null) {
if (log.isTraceEnabled()) {
log.trace("block {} already cached", block.getShortHash());
}
return PropStatus.DROPPED;
}
// regardless if block processing is successful, place into cache
this.cacheMap.put(hashWrapped, true);
}
// process
long t1 = System.currentTimeMillis();
ImportResult result;
if (this.blockchain.skipTryToConnect(block.getNumber())) {
result = ImportResult.NO_PARENT;
if (log.isInfoEnabled()) {
log.info("<import-status: node = {}, hash = {}, number = {}, txs = {}, result = NOT_IN_RANGE>", displayId, block.getShortHash(), block.getNumber(), block.getTransactionsList().size(), result);
} else if (log.isDebugEnabled()) {
log.debug("<import-status: node = {}, hash = {}, number = {}, txs = {}, block time = {}, result = NOT_IN_RANGE>", displayId, block.getShortHash(), block.getNumber(), block.getTransactionsList().size(), block.getTimestamp(), result);
}
} else {
result = this.blockchain.tryToConnect(new BlockWrapper(block));
long t2 = System.currentTimeMillis();
if (result.isStored()) {
this.syncStats.updatePeerBlocks(displayId, 1, BlockType.IMPORTED);
}
if (log.isInfoEnabled()) {
log.info("<import-status: node = {}, hash = {}, number = {}, txs = {}, result = {}, time elapsed = {} ms>", displayId, block.getShortHash(), block.getNumber(), block.getTransactionsList().size(), result, t2 - t1);
} else if (log.isDebugEnabled()) {
log.debug("<import-status: node = {}, hash = {}, number = {}, td = {}, txs = {}, block time = {}, result = {}, time elapsed = {} ms>", displayId, block.getShortHash(), block.getNumber(), blockchain.getTotalDifficulty(), block.getTransactionsList().size(), block.getTimestamp(), result, t2 - t1);
}
}
// send
boolean sent = result.isBest() && send(block, nodeId);
// notify higher td peers in order to limit the rebroadcast on delay of res status updating
if (result.isBest()) {
Block bestBlock = blockchain.getBestBlock();
BigInteger td = bestBlock.getTotalDifficulty();
ResStatus rs = new ResStatus(bestBlock.getNumber(), td.toByteArray(), bestBlock.getHash(), genesis, apiVersion, (short) p2pManager.getActiveNodes().size(), BigInteger.valueOf(this.pendingState.getPendingTxSize()).toByteArray(), p2pManager.getAvgLatency());
this.p2pManager.getActiveNodes().values().stream().filter(n -> n.getIdHash() != nodeId).filter(n -> n.getTotalDifficulty().compareTo(td) >= 0).forEach(n -> {
log.debug("<push-status blk={} hash={} to-node={} dd={} import-result={}>", block.getNumber(), block.getShortHash(), n.getIdShort(), td.longValue() - n.getTotalDifficulty().longValue(), result.name());
this.p2pManager.send(n.getIdHash(), n.getIdShort(), rs);
});
}
// process resulting state
if (sent && result.isSuccessful())
return PropStatus.PROP_CONNECTED;
if (result.isSuccessful())
return PropStatus.CONNECTED;
if (sent)
return PropStatus.PROPAGATED;
// gets dropped when the result is not valid
return PropStatus.DROPPED;
}
use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class BlockPropagationHandler method send.
private boolean send(Block block, int nodeId) {
if (isSyncOnlyNode)
return true;
// current proposal is to send to all peers with lower blockNumbers
AtomicBoolean sent = new AtomicBoolean();
this.p2pManager.getActiveNodes().values().stream().filter(n -> n.getIdHash() != nodeId).filter(n -> {
long delta = block.getNumber() - n.getBestBlockNumber();
return (delta >= 0 && delta <= 100) || (n.getBestBlockNumber() == 0);
}).forEach(n -> {
if (log.isDebugEnabled())
log.debug("<sending-new-block hash=" + block.getShortHash() + " to-node=" + n.getIdShort() + ">");
this.p2pManager.send(n.getIdHash(), n.getIdShort(), new BroadcastNewBlock(block));
sent.getAndSet(true);
});
return sent.get();
}
use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class SyncMgr method requestBodies.
/**
* Requests the bodies associated to the given block headers.
*/
void requestBodies(int nodeId, String displayId) {
Thread.currentThread().setName("sync-gb-" + Thread.currentThread().getId());
long startTime = System.nanoTime();
List<List<BlockHeader>> forRequests = syncHeaderRequestManager.getHeadersForBodiesRequests(nodeId);
for (List<BlockHeader> requestHeaders : forRequests) {
// Filter headers again in case the blockchain has advanced while this task was waiting to be executed.
List<BlockHeader> filtered = requestHeaders.stream().filter(h -> !importedBlockHashes.containsKey(ByteArrayWrapper.wrap(h.getHash()))).collect(Collectors.toList());
// Check the peer state and discard blocks that are under the current best (in case the hashes already dropped from the above map).
// This check is only applicable for SyncMode.NORMAL because the other sync modes deal with side chains.
long currentBest = chain.getBestBlock() == null ? 0L : chain.getBestBlock().getNumber();
long firstInBatch = requestHeaders.get(0).getNumber();
if (syncHeaderRequestManager.getSyncMode(nodeId) == SyncMode.NORMAL && firstInBatch <= currentBest) {
// remove all blocks in the batch that are under the current best
for (Iterator<BlockHeader> it = filtered.iterator(); it.hasNext(); ) {
if (it.next().getNumber() <= currentBest) {
it.remove();
}
}
}
if (filtered.size() == requestHeaders.size()) {
// Log bodies request before sending the request.
log.debug("<get-bodies from-num={} to-num={} node={}>", firstInBatch, requestHeaders.get(requestHeaders.size() - 1).getNumber(), displayId);
p2pMgr.send(nodeId, displayId, new ReqBlocksBodies(requestHeaders.stream().map(k -> k.getHash()).collect(Collectors.toList())));
stats.updateTotalRequestsToPeer(displayId, RequestType.BODIES);
stats.updateRequestTime(displayId, System.nanoTime(), RequestType.BODIES);
} else {
// Drop the headers that are already known.
syncHeaderRequestManager.dropHeaders(nodeId, requestHeaders);
if (!filtered.isEmpty()) {
// Store the subset that is still useful.
syncHeaderRequestManager.storeHeaders(nodeId, filtered);
}
}
}
long duration = System.nanoTime() - startTime;
survey_log.debug("TaskGetBodies: make request, duration = {} ns.", duration);
}
use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class SyncMgr method getStatus.
private static String getStatus(AionBlockchainImpl chain, NetworkStatus networkStatus, SyncStats syncStats) {
Block selfBest = chain.getBestBlock();
String selfTd = selfBest.getTotalDifficulty().toString(10);
return "sync-status avg-import=" + String.format("%.2f", syncStats.getAvgBlocksPerSec()) + " b/s" + " td=" + selfTd + "/" + networkStatus.getTargetTotalDiff().toString(10) + " b-num=" + selfBest.getNumber() + "/" + networkStatus.getTargetBestBlockNumber() + " b-hash=" + Hex.toHexString(chain.getBestBlockHash()) + "/" + networkStatus.getTargetBestBlockHash();
}
use of org.aion.zero.impl.types.Block in project aion by aionnetwork.
the class AionPendingStateImpl method executeTx.
private AionTxExecSummary executeTx(AionTransaction tx) {
Block bestBlk = currentBestBlock.get();
LOGGER_TX.debug("executeTx: {}", Hex.toHexString(tx.getTransactionHash()));
try {
// Booleans moved out here so their meaning is explicit.
boolean isLocalCall = false;
boolean incrementSenderNonce = true;
boolean checkBlockEnergyLimit = false;
// this parameter should not be relevant to execution
byte[] difficulty = bestBlk.getDifficulty();
// the pending state is executed on top of the best block
long currentBlockNumber = bestBlk.getNumber() + 1;
// simulating future block
long timestamp = bestBlk.getTimestamp() + 1;
// the limit is not checked so making it unlimited
long blockNrgLimit = Long.MAX_VALUE;
// assuming same person will mine the future block
AionAddress miner = bestBlk.getCoinbase();
return BulkExecutor.executeTransactionWithNoPostExecutionWork(difficulty, currentBlockNumber, timestamp, blockNrgLimit, miner, tx, pendingState, isLocalCall, incrementSenderNonce, blockchain.forkUtility.is040ForkActive(currentBlockNumber), checkBlockEnergyLimit, LOGGER_VM, BlockCachingContext.PENDING, bestBlk.getNumber(), blockchain.forkUtility.isUnityForkActive(currentBlockNumber), blockchain.forkUtility.isSignatureSwapForkActive(currentBlockNumber));
} catch (VmFatalException e) {
LOGGER_VM.error("Shutdown due to a VM fatal error.", e);
System.exit(SystemExitCodes.FATAL_VM_ERROR);
return null;
}
}
Aggregations