@ -17,6 +17,7 @@ import tech.pegasys.pantheon.ethereum.chain.BlockAddedEvent;
import tech.pegasys.pantheon.ethereum.chain.BlockAddedEvent.EventType ;
import tech.pegasys.pantheon.ethereum.chain.BlockAddedEvent.EventType ;
import tech.pegasys.pantheon.ethereum.chain.Blockchain ;
import tech.pegasys.pantheon.ethereum.chain.Blockchain ;
import tech.pegasys.pantheon.ethereum.core.Block ;
import tech.pegasys.pantheon.ethereum.core.Block ;
import tech.pegasys.pantheon.ethereum.core.BlockHeader ;
import tech.pegasys.pantheon.ethereum.core.Hash ;
import tech.pegasys.pantheon.ethereum.core.Hash ;
import tech.pegasys.pantheon.ethereum.eth.manager.AbstractPeerTask ;
import tech.pegasys.pantheon.ethereum.eth.manager.AbstractPeerTask ;
import tech.pegasys.pantheon.ethereum.eth.manager.EthContext ;
import tech.pegasys.pantheon.ethereum.eth.manager.EthContext ;
@ -30,8 +31,10 @@ import tech.pegasys.pantheon.ethereum.eth.sync.state.PendingBlocks;
import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState ;
import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState ;
import tech.pegasys.pantheon.ethereum.eth.sync.tasks.GetBlockFromPeerTask ;
import tech.pegasys.pantheon.ethereum.eth.sync.tasks.GetBlockFromPeerTask ;
import tech.pegasys.pantheon.ethereum.eth.sync.tasks.PersistBlockTask ;
import tech.pegasys.pantheon.ethereum.eth.sync.tasks.PersistBlockTask ;
import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator ;
import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode ;
import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode ;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule ;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule ;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec ;
import tech.pegasys.pantheon.ethereum.p2p.wire.messages.DisconnectMessage.DisconnectReason ;
import tech.pegasys.pantheon.ethereum.p2p.wire.messages.DisconnectMessage.DisconnectReason ;
import tech.pegasys.pantheon.ethereum.rlp.RLPException ;
import tech.pegasys.pantheon.ethereum.rlp.RLPException ;
import tech.pegasys.pantheon.metrics.LabelledMetric ;
import tech.pegasys.pantheon.metrics.LabelledMetric ;
@ -63,6 +66,7 @@ public class BlockPropagationManager<C> {
private final EthContext ethContext ;
private final EthContext ethContext ;
private final SyncState syncState ;
private final SyncState syncState ;
private final LabelledMetric < OperationTimer > ethTasksTimer ;
private final LabelledMetric < OperationTimer > ethTasksTimer ;
private final BlockBroadcaster blockBroadcaster ;
private final AtomicBoolean started = new AtomicBoolean ( false ) ;
private final AtomicBoolean started = new AtomicBoolean ( false ) ;
@ -77,13 +81,14 @@ public class BlockPropagationManager<C> {
final EthContext ethContext ,
final EthContext ethContext ,
final SyncState syncState ,
final SyncState syncState ,
final PendingBlocks pendingBlocks ,
final PendingBlocks pendingBlocks ,
final LabelledMetric < OperationTimer > ethTasksTimer ) {
final LabelledMetric < OperationTimer > ethTasksTimer ,
final BlockBroadcaster blockBroadcaster ) {
this . config = config ;
this . config = config ;
this . protocolSchedule = protocolSchedule ;
this . protocolSchedule = protocolSchedule ;
this . protocolContext = protocolContext ;
this . protocolContext = protocolContext ;
this . ethContext = ethContext ;
this . ethContext = ethContext ;
this . ethTasksTimer = ethTasksTimer ;
this . ethTasksTimer = ethTasksTimer ;
this . blockBroadcaster = blockBroadcaster ;
this . syncState = syncState ;
this . syncState = syncState ;
this . pendingBlocks = pendingBlocks ;
this . pendingBlocks = pendingBlocks ;
}
}
@ -105,6 +110,32 @@ public class BlockPropagationManager<C> {
. subscribe ( EthPV62 . NEW_BLOCK_HASHES , this : : handleNewBlockHashesFromNetwork ) ;
. subscribe ( EthPV62 . NEW_BLOCK_HASHES , this : : handleNewBlockHashesFromNetwork ) ;
}
}
protected void validateAndBroadcastBlock ( final Block block ) {
final ProtocolSpec < C > protocolSpec =
protocolSchedule . getByBlockNumber ( block . getHeader ( ) . getNumber ( ) ) ;
final BlockHeaderValidator < C > blockHeaderValidator = protocolSpec . getBlockHeaderValidator ( ) ;
final BlockHeader parent =
protocolContext
. getBlockchain ( )
. getBlockHeader ( block . getHeader ( ) . getParentHash ( ) )
. orElseThrow (
( ) - >
new IllegalArgumentException (
"Incapable of retrieving header from non-existent parent of "
+ block . getHeader ( ) . getNumber ( )
+ "." ) ) ;
if ( blockHeaderValidator . validateHeader (
block . getHeader ( ) , parent , protocolContext , HeaderValidationMode . FULL ) ) {
final UInt256 totalDifficulty =
protocolContext
. getBlockchain ( )
. getTotalDifficultyByHash ( parent . getHash ( ) )
. get ( )
. plus ( block . getHeader ( ) . getDifficulty ( ) ) ;
blockBroadcaster . propagate ( block , totalDifficulty ) ;
}
}
private void onBlockAdded ( final BlockAddedEvent blockAddedEvent , final Blockchain blockchain ) {
private void onBlockAdded ( final BlockAddedEvent blockAddedEvent , final Blockchain blockchain ) {
// Check to see if any of our pending blocks are now ready for import
// Check to see if any of our pending blocks are now ready for import
final Block newBlock = blockAddedEvent . getBlock ( ) ;
final Block newBlock = blockAddedEvent . getBlock ( ) ;
@ -144,13 +175,6 @@ public class BlockPropagationManager<C> {
}
}
}
}
void broadcastBlock ( final Block block , final UInt256 difficulty ) {
ethContext
. getEthPeers ( )
. availablePeers ( )
. forEach ( ethPeer - > ethPeer . propagateBlock ( block , difficulty ) ) ;
}
void handleNewBlockFromNetwork ( final EthMessage message ) {
void handleNewBlockFromNetwork ( final EthMessage message ) {
final Blockchain blockchain = protocolContext . getBlockchain ( ) ;
final Blockchain blockchain = protocolContext . getBlockchain ( ) ;
final NewBlockMessage newBlockMessage = NewBlockMessage . readFrom ( message . getData ( ) ) ;
final NewBlockMessage newBlockMessage = NewBlockMessage . readFrom ( message . getData ( ) ) ;
@ -158,9 +182,6 @@ public class BlockPropagationManager<C> {
final Block block = newBlockMessage . block ( protocolSchedule ) ;
final Block block = newBlockMessage . block ( protocolSchedule ) ;
final UInt256 totalDifficulty = newBlockMessage . totalDifficulty ( protocolSchedule ) ;
final UInt256 totalDifficulty = newBlockMessage . totalDifficulty ( protocolSchedule ) ;
// TODO: Extract broadcast functionality to independent class.
// broadcastBlock(block, totalDifficulty);
message . getPeer ( ) . chainState ( ) . updateForAnnouncedBlock ( block . getHeader ( ) , totalDifficulty ) ;
message . getPeer ( ) . chainState ( ) . updateForAnnouncedBlock ( block . getHeader ( ) , totalDifficulty ) ;
// Return early if we don't care about this block
// Return early if we don't care about this block
@ -272,6 +293,8 @@ public class BlockPropagationManager<C> {
return CompletableFuture . completedFuture ( block ) ;
return CompletableFuture . completedFuture ( block ) ;
}
}
validateAndBroadcastBlock ( block ) ;
// Import block
// Import block
final PersistBlockTask < C > importTask =
final PersistBlockTask < C > importTask =
PersistBlockTask . create (
PersistBlockTask . create (