use of org.hyperledger.besu.ethereum.core.Block in project besu by hyperledger.
the class BlockBroadcaster method propagate.
public void propagate(final Block block, final Difficulty totalDifficulty) {
blockPropagatedSubscribers.forEach(listener -> listener.accept(block, totalDifficulty));
final NewBlockMessage newBlockMessage = NewBlockMessage.create(block, totalDifficulty);
ethContext.getEthPeers().streamAvailablePeers().filter(ethPeer -> !ethPeer.hasSeenBlock(block.getHash())).forEach(ethPeer -> {
ethPeer.registerKnownBlock(block.getHash());
try {
ethPeer.send(newBlockMessage);
} catch (final PeerConnection.PeerNotConnected e) {
LOG.trace("Failed to broadcast new block to peer", e);
}
});
}
use of org.hyperledger.besu.ethereum.core.Block in project besu by hyperledger.
the class BlockPropagationManager method onBlockAdded.
private void onBlockAdded(final BlockAddedEvent blockAddedEvent) {
// Check to see if any of our pending blocks are now ready for import
final Block newBlock = blockAddedEvent.getBlock();
final List<Block> readyForImport;
synchronized (pendingBlocksManager) {
// Remove block from pendingBlocks list
pendingBlocksManager.deregisterPendingBlock(newBlock);
// Import any pending blocks that are children of the newly added block
readyForImport = pendingBlocksManager.childrenOf(newBlock.getHash());
}
traceLambda(LOG, "Block added event type {} for block {}. Current status {}", blockAddedEvent::getEventType, newBlock::toLogString, () -> this);
if (!readyForImport.isEmpty()) {
traceLambda(LOG, "Ready to import pending blocks found [{}] for block {}", () -> readyForImport.stream().map(Block::toLogString).collect(Collectors.joining(", ")), newBlock::toLogString);
final Supplier<CompletableFuture<List<Block>>> importBlocksTask = PersistBlockTask.forUnorderedBlocks(protocolSchedule, protocolContext, ethContext, readyForImport, HeaderValidationMode.FULL, metricsSystem);
ethContext.getScheduler().scheduleSyncWorkerTask(importBlocksTask).whenComplete((r, t) -> {
if (r != null) {
LOG.info("Imported {} pending blocks", r.size());
}
if (t != null) {
LOG.error("Error importing pending blocks", t);
}
});
} else {
traceLambda(LOG, "There are no pending blocks ready to import for block {}", newBlock::toLogString);
maybeProcessNonAnnouncedBlocks(newBlock);
}
if (blockAddedEvent.getEventType().equals(EventType.HEAD_ADVANCED)) {
final long head = protocolContext.getBlockchain().getChainHeadBlockNumber();
final long cutoff = head + config.getBlockPropagationRange().lowerEndpoint();
pendingBlocksManager.purgeBlocksOlderThan(cutoff);
}
}
use of org.hyperledger.besu.ethereum.core.Block in project besu by hyperledger.
the class BlockPropagationManager method getBlockFromPeers.
private CompletableFuture<Block> getBlockFromPeers(final Optional<EthPeer> preferredPeer, final long blockNumber, final Optional<Hash> blockHash) {
final RetryingGetBlockFromPeersTask getBlockTask = RetryingGetBlockFromPeersTask.create(protocolContext, protocolSchedule, ethContext, metricsSystem, ethContext.getEthPeers().getMaxPeers(), blockHash, blockNumber);
preferredPeer.ifPresent(getBlockTask::assignPeer);
return ethContext.getScheduler().scheduleSyncWorkerTask(getBlockTask::run).thenCompose(r -> importOrSavePendingBlock(r.getResult(), r.getPeer().nodeId())).whenComplete((r, t) -> {
requestedNonAnnouncedBlocks.remove(blockNumber);
blockHash.ifPresentOrElse(requestedBlocks::remove, () -> {
if (r != null) {
// in case we successfully retrieved only by block number, when can remove
// the request by hash too
requestedBlocks.remove(r.getHash());
}
});
});
}
use of org.hyperledger.besu.ethereum.core.Block in project besu by hyperledger.
the class ForwardSyncStep method saveBlocks.
@VisibleForTesting
protected Void saveBlocks(final List<Block> blocks) {
if (blocks.isEmpty()) {
LOG.info("No blocks to save...");
context.halveBatchSize();
return null;
}
for (Block block : blocks) {
final Optional<Block> parent = context.getProtocolContext().getBlockchain().getBlockByHash(block.getHeader().getParentHash());
if (parent.isEmpty()) {
context.halveBatchSize();
return null;
} else {
saveBlock(block);
}
}
infoLambda(LOG, "Saved blocks {} -> {} (target: {})", () -> blocks.get(0).getHeader().getNumber(), () -> blocks.get(blocks.size() - 1).getHeader().getNumber(), () -> backwardChain.getPivot().orElse(blocks.get(blocks.size() - 1)).getHeader().getNumber());
context.resetBatchSize();
return null;
}
use of org.hyperledger.besu.ethereum.core.Block in project besu by hyperledger.
the class TransactionPoolTest method shouldReadTransactionsFromThePreviousCanonicalHeadWhenAReorgOccurs.
@Test
public void shouldReadTransactionsFromThePreviousCanonicalHeadWhenAReorgOccurs() {
givenTransactionIsValid(transaction1);
givenTransactionIsValid(transaction2);
transactions.addRemoteTransaction(transaction1);
transactions.addRemoteTransaction(transaction2);
final BlockHeader commonParent = getHeaderForCurrentChainHead();
final Block originalFork1 = appendBlock(Difficulty.of(1000), commonParent, transaction1);
final Block originalFork2 = appendBlock(Difficulty.ONE, originalFork1.getHeader(), transaction2);
assertTransactionNotPending(transaction1);
assertTransactionNotPending(transaction2);
final Block reorgFork1 = appendBlock(Difficulty.ONE, commonParent);
verifyChainHeadIs(originalFork2);
transactions.subscribePendingTransactions(listener);
final Block reorgFork2 = appendBlock(Difficulty.of(2000), reorgFork1.getHeader());
verifyChainHeadIs(reorgFork2);
assertTransactionPending(transaction1);
assertTransactionPending(transaction2);
verify(listener).onTransactionAdded(transaction1);
verify(listener).onTransactionAdded(transaction2);
verifyNoMoreInteractions(listener);
}
Aggregations