diff --git a/src/it/scala/io/iohk/ethereum/sync/util/CommonFakePeer.scala b/src/it/scala/io/iohk/ethereum/sync/util/CommonFakePeer.scala index 983796892e..772a595816 100644 --- a/src/it/scala/io/iohk/ethereum/sync/util/CommonFakePeer.scala +++ b/src/it/scala/io/iohk/ethereum/sync/util/CommonFakePeer.scala @@ -6,6 +6,7 @@ import java.util.concurrent.atomic.AtomicReference import akka.actor.{ActorRef, ActorSystem} import akka.testkit.TestProbe import akka.util.{ByteString, Timeout} +import io.iohk.ethereum.blockchain.sync.regular.BlockBroadcast.BlockToBroadcast import io.iohk.ethereum.blockchain.sync.regular.{BlockBroadcast, BlockBroadcasterActor} import io.iohk.ethereum.blockchain.sync.regular.BlockBroadcasterActor.BroadcastBlock import io.iohk.ethereum.blockchain.sync.{BlockchainHostActor, TestSyncConfig} @@ -18,11 +19,10 @@ import io.iohk.ethereum.ledger.InMemoryWorldStateProxy import io.iohk.ethereum.mpt.MerklePatriciaTrie import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo import io.iohk.ethereum.network.PeerManagerActor.{FastSyncHostConfiguration, PeerConfiguration} -import io.iohk.ethereum.network.discovery.{DiscoveryConfig, Node} import io.iohk.ethereum.network.discovery.PeerDiscoveryManager.DiscoveredNodesInfo +import io.iohk.ethereum.network.discovery.{DiscoveryConfig, Node} import io.iohk.ethereum.network.handshaker.{EtcHandshaker, EtcHandshakerConfiguration, Handshaker} import io.iohk.ethereum.network.p2p.EthereumMessageDecoder -import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock import io.iohk.ethereum.network.rlpx.AuthHandshaker import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler.RLPxConfiguration import io.iohk.ethereum.network.{ @@ -159,7 +159,7 @@ abstract class CommonFakePeer(peerName: String, fakePeerCustomConfig: FakePeerCu override val peerConfiguration: PeerConfiguration = peerConf override val blockchain: Blockchain = bl override val appStateStorage: AppStateStorage = storagesInstance.storages.appStateStorage - override val blockchainConfig = CommonFakePeer.this.blockchainConfig // FIXME: remove in ETCM-280 + override val protocolVersion: Int = Config.Network.protocolVersion } lazy val handshaker: Handshaker[PeerInfo] = EtcHandshaker(handshakerConfiguration) @@ -175,7 +175,8 @@ abstract class CommonFakePeer(peerName: String, fakePeerCustomConfig: FakePeerCu handshaker, authHandshaker, EthereumMessageDecoder, - discoveryConfig + discoveryConfig, + Config.Network.protocolVersion ), "peer-manager" ) @@ -227,7 +228,7 @@ abstract class CommonFakePeer(peerName: String, fakePeerCustomConfig: FakePeerCu } private def broadcastBlock(block: Block, weight: ChainWeight) = { - broadcasterActor ! BroadcastBlock(NewBlock(block, weight)) + broadcasterActor ! BroadcastBlock(BlockToBroadcast(block, weight)) } def getCurrentState(): BlockchainState = { diff --git a/src/it/scala/io/iohk/ethereum/sync/util/RegularSyncItSpecUtils.scala b/src/it/scala/io/iohk/ethereum/sync/util/RegularSyncItSpecUtils.scala index 4e4a36dcb9..c7d53043a1 100644 --- a/src/it/scala/io/iohk/ethereum/sync/util/RegularSyncItSpecUtils.scala +++ b/src/it/scala/io/iohk/ethereum/sync/util/RegularSyncItSpecUtils.scala @@ -4,16 +4,16 @@ import akka.actor.ActorRef import akka.util.ByteString import cats.effect.Resource import io.iohk.ethereum.Mocks.MockValidatorsAlwaysSucceed -import io.iohk.ethereum.blockchain.sync.{PeersClient, SyncProtocol} +import io.iohk.ethereum.blockchain.sync.regular.BlockBroadcast.BlockToBroadcast import io.iohk.ethereum.blockchain.sync.regular.BlockBroadcasterActor.BroadcastBlock import io.iohk.ethereum.blockchain.sync.regular.RegularSync +import io.iohk.ethereum.blockchain.sync.{PeersClient, SyncProtocol} import io.iohk.ethereum.consensus.Protocol.NoAdditionalEthashData import io.iohk.ethereum.consensus.blocks.CheckpointBlockGenerator import io.iohk.ethereum.consensus.ethash.{EthashConfig, EthashConsensus} import io.iohk.ethereum.consensus.{ConsensusConfig, FullConsensusConfig, ethash} import io.iohk.ethereum.domain._ import io.iohk.ethereum.ledger._ -import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock import io.iohk.ethereum.nodebuilder.VmSetup import io.iohk.ethereum.ommers.OmmersPool import io.iohk.ethereum.sync.util.SyncCommonItSpecUtils.FakePeerCustomConfig.defaultConfig @@ -74,7 +74,6 @@ object RegularSyncItSpecUtils { peerEventBus, ledger, bl, - blockchainConfig, // FIXME: remove in ETCM-280 validators.blockValidator, testSyncConfig, ommersPool, @@ -145,7 +144,7 @@ object RegularSyncItSpecUtils { } private def broadcastBlock(block: Block, weight: ChainWeight) = { - broadcasterActor ! BroadcastBlock(NewBlock(block, weight)) + broadcasterActor ! BroadcastBlock(BlockToBroadcast(block, weight)) } private def createChildBlock( diff --git a/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainActor.scala b/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainActor.scala index 43c111f926..073f3de8bf 100644 --- a/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainActor.scala +++ b/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainActor.scala @@ -6,26 +6,27 @@ import java.net.URI import akka.actor.{Actor, ActorRef, _} import akka.util.ByteString import io.iohk.ethereum.crypto.kec256 -import io.iohk.ethereum.domain.{BlockBody, BlockHeader, Receipt} import io.iohk.ethereum.domain.BlockHeaderImplicits._ -import io.iohk.ethereum.network.{Peer, PeerManagerActor} +import io.iohk.ethereum.domain.{BlockBody, BlockHeader, Receipt} +import io.iohk.ethereum.mpt.{BranchNode, ExtensionNode, HashNode, LeafNode, MptNode} import io.iohk.ethereum.network.PeerActor.SendMessage +import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.MessageFromPeer +import io.iohk.ethereum.network.PeerEventBusActor.SubscriptionClassifier.MessageClassifier +import io.iohk.ethereum.network.PeerEventBusActor.{PeerSelector, Subscribe} import io.iohk.ethereum.network.PeerManagerActor.{GetPeers, Peers} +import io.iohk.ethereum.network.p2p.messages.Codes import io.iohk.ethereum.network.p2p.messages.PV62._ -import io.iohk.ethereum.network.p2p.messages.PV63._ import io.iohk.ethereum.network.p2p.messages.PV63.MptNodeEncoders._ +import io.iohk.ethereum.network.p2p.messages.PV63.ReceiptImplicits._ +import io.iohk.ethereum.network.p2p.messages.PV63._ +import io.iohk.ethereum.network.{Peer, PeerManagerActor} +import io.iohk.ethereum.txExecTest.util.DumpChainActor._ import org.bouncycastle.util.encoders.Hex -import ReceiptImplicits._ -import io.iohk.ethereum.mpt.{BranchNode, ExtensionNode, HashNode, LeafNode, MptNode} -import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.MessageFromPeer -import io.iohk.ethereum.network.PeerEventBusActor.{PeerSelector, Subscribe} -import io.iohk.ethereum.network.PeerEventBusActor.SubscriptionClassifier.MessageClassifier import scala.collection.immutable.HashMap import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration._ import scala.language.postfixOps -import DumpChainActor._ /** * Actor used for obtaining all the blockchain data (blocks, receipts, nodes) from the blocks [startBlock, maxBlocks] @@ -84,7 +85,7 @@ class DumpChainActor( peers.headOption.foreach { peer => peerMessageBus ! Subscribe( MessageClassifier( - Set(BlockHeaders.code, BlockBodies.code, Receipts.code, NodeData.code), + Set(Codes.BlockHeadersCode, Codes.BlockBodiesCode, Codes.ReceiptsCode, Codes.NodeDataCode), PeerSelector.WithId(peer.id) ) ) diff --git a/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainApp.scala b/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainApp.scala index a1b5e4bbfa..da16612342 100644 --- a/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainApp.scala +++ b/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainApp.scala @@ -1,34 +1,34 @@ package io.iohk.ethereum.txExecTest.util +import java.util.concurrent.atomic.AtomicReference + import akka.actor.ActorSystem import akka.util.ByteString import com.typesafe.config.ConfigFactory import io.iohk.ethereum.db.components.Storages.PruningModeComponent import io.iohk.ethereum.db.components.{RocksDbDataSourceComponent, Storages} -import io.iohk.ethereum.db.storage.{AppStateStorage, StateStorage} +import io.iohk.ethereum.db.dataSource.{DataSourceBatchUpdate, RocksDbDataSource} import io.iohk.ethereum.db.storage.NodeStorage.{NodeEncoded, NodeHash} import io.iohk.ethereum.db.storage.TransactionMappingStorage.TransactionLocation import io.iohk.ethereum.db.storage.pruning.{ArchivePruning, PruningMode} +import io.iohk.ethereum.db.storage.{AppStateStorage, StateStorage} +import io.iohk.ethereum.domain.BlockHeader.HeaderExtraFields.HefEmpty import io.iohk.ethereum.domain.{Blockchain, UInt256, _} import io.iohk.ethereum.ledger.{InMemoryWorldStateProxy, InMemoryWorldStateProxyStorage} import io.iohk.ethereum.mpt.MptNode import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo import io.iohk.ethereum.network.PeerManagerActor.PeerConfiguration +import io.iohk.ethereum.network.discovery.DiscoveryConfig import io.iohk.ethereum.network.handshaker.{EtcHandshaker, EtcHandshakerConfiguration, Handshaker} import io.iohk.ethereum.network.p2p.EthereumMessageDecoder import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler.RLPxConfiguration import io.iohk.ethereum.network.{ForkResolver, PeerEventBusActor, PeerManagerActor} import io.iohk.ethereum.nodebuilder.{AuthHandshakerBuilder, NodeKeyBuilder, SecureRandomBuilder} -import io.iohk.ethereum.utils.{BlockchainConfig, Config, NodeStatus, ServerStatus} -import java.util.concurrent.atomic.AtomicReference - -import io.iohk.ethereum.db.dataSource.{DataSourceBatchUpdate, RocksDbDataSource} +import io.iohk.ethereum.utils.{Config, NodeStatus, ServerStatus} +import monix.reactive.Observable import org.bouncycastle.util.encoders.Hex import scala.concurrent.duration._ -import io.iohk.ethereum.domain.BlockHeader.HeaderExtraFields.HefEmpty -import io.iohk.ethereum.network.discovery.DiscoveryConfig -import monix.reactive.Observable object DumpChainApp extends App with NodeKeyBuilder with SecureRandomBuilder with AuthHandshakerBuilder { val conf = ConfigFactory.load("txExecTest/chainDump.conf") @@ -82,8 +82,8 @@ object DumpChainApp extends App with NodeKeyBuilder with SecureRandomBuilder wit override val nodeStatusHolder: AtomicReference[NodeStatus] = DumpChainApp.nodeStatusHolder override val peerConfiguration: PeerConfiguration = peerConfig override val blockchain: Blockchain = DumpChainApp.blockchain - override val blockchainConfig: BlockchainConfig = DumpChainApp.blockchainConfig override val appStateStorage: AppStateStorage = storagesInstance.storages.appStateStorage + override val protocolVersion: Int = Config.Network.protocolVersion } lazy val handshaker: Handshaker[PeerInfo] = EtcHandshaker(handshakerConfiguration) @@ -99,7 +99,8 @@ object DumpChainApp extends App with NodeKeyBuilder with SecureRandomBuilder wit handshaker = handshaker, authHandshaker = authHandshaker, messageDecoder = EthereumMessageDecoder, - discoveryConfig + discoveryConfig, + Config.Network.protocolVersion ), "peer-manager" ) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index bd28bfcd33..c1fc668b31 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -38,6 +38,8 @@ mantis { network { # Ethereum protocol version + # Supported versions: + # 63, 64 (experimental version which enables usage of messages with checkpointing information. In the future after ETCM-355, ETCM-356, it will be 66 probably) protocol-version = 63 server-address { diff --git a/src/main/scala/io/iohk/ethereum/blockchain/sync/BlockchainHostActor.scala b/src/main/scala/io/iohk/ethereum/blockchain/sync/BlockchainHostActor.scala index f3e1c3f133..eafb592d11 100644 --- a/src/main/scala/io/iohk/ethereum/blockchain/sync/BlockchainHostActor.scala +++ b/src/main/scala/io/iohk/ethereum/blockchain/sync/BlockchainHostActor.scala @@ -12,6 +12,7 @@ import io.iohk.ethereum.network.p2p.messages.PV62.{BlockBodies, BlockHeaders, Ge import io.iohk.ethereum.network.p2p.messages.PV63.{GetNodeData, GetReceipts, NodeData, Receipts} import io.iohk.ethereum.network.p2p.messages.PV63.MptNodeEncoders._ import io.iohk.ethereum.network.EtcPeerManagerActor +import io.iohk.ethereum.network.p2p.messages.Codes /** * BlockchainHost actor is in charge of replying to the peer's requests for blockchain data, which includes both @@ -25,7 +26,8 @@ class BlockchainHostActor( ) extends Actor with ActorLogging { - private val requestMsgsCodes = Set(GetNodeData.code, GetReceipts.code, GetBlockBodies.code, GetBlockHeaders.code) + private val requestMsgsCodes = + Set(Codes.GetNodeDataCode, Codes.GetReceiptsCode, Codes.GetBlockBodiesCode, Codes.GetBlockHeadersCode) peerEventBusActor ! Subscribe(MessageClassifier(requestMsgsCodes, PeerSelector.AllPeers)) override def receive: Receive = { case MessageFromPeer(message, peerId) => diff --git a/src/main/scala/io/iohk/ethereum/blockchain/sync/PeersClient.scala b/src/main/scala/io/iohk/ethereum/blockchain/sync/PeersClient.scala index ac823f4916..c46a08d5e6 100644 --- a/src/main/scala/io/iohk/ethereum/blockchain/sync/PeersClient.scala +++ b/src/main/scala/io/iohk/ethereum/blockchain/sync/PeersClient.scala @@ -2,6 +2,7 @@ package io.iohk.ethereum.blockchain.sync import akka.actor.{Actor, ActorLogging, ActorRef, Cancellable, Props, Scheduler} import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo +import io.iohk.ethereum.network.p2p.messages.Codes import io.iohk.ethereum.network.{Peer, PeerId} import io.iohk.ethereum.network.p2p.messages.PV62._ import io.iohk.ethereum.network.p2p.messages.PV63.{GetNodeData, NodeData} @@ -94,9 +95,9 @@ class PeersClient( private def responseMsgCode[RequestMsg <: Message](requestMsg: RequestMsg): Int = requestMsg match { - case _: GetBlockHeaders => BlockHeaders.code - case _: GetBlockBodies => BlockBodies.code - case _: GetNodeData => NodeData.code + case _: GetBlockHeaders => Codes.BlockHeadersCode + case _: GetBlockBodies => Codes.BlockBodiesCode + case _: GetNodeData => Codes.NodeDataCode } private def printStatus(requesters: Requesters): Unit = { diff --git a/src/main/scala/io/iohk/ethereum/blockchain/sync/SyncController.scala b/src/main/scala/io/iohk/ethereum/blockchain/sync/SyncController.scala index 2f3e29319e..8c53b4df82 100644 --- a/src/main/scala/io/iohk/ethereum/blockchain/sync/SyncController.scala +++ b/src/main/scala/io/iohk/ethereum/blockchain/sync/SyncController.scala @@ -8,13 +8,11 @@ import io.iohk.ethereum.consensus.validators.Validators import io.iohk.ethereum.db.storage.{AppStateStorage, FastSyncStateStorage} import io.iohk.ethereum.domain.Blockchain import io.iohk.ethereum.ledger.Ledger -import io.iohk.ethereum.utils.BlockchainConfig import io.iohk.ethereum.utils.Config.SyncConfig class SyncController( appStateStorage: AppStateStorage, blockchain: Blockchain, - blockchainConfig: BlockchainConfig, fastSyncStateStorage: FastSyncStateStorage, ledger: Ledger, validators: Validators, @@ -102,7 +100,6 @@ class SyncController( peerEventBus, ledger, blockchain, - blockchainConfig, validators.blockValidator, syncConfig, ommersPool, @@ -123,7 +120,6 @@ object SyncController { def props( appStateStorage: AppStateStorage, blockchain: Blockchain, - blockchainConfig: BlockchainConfig, syncStateStorage: FastSyncStateStorage, ledger: Ledger, validators: Validators, @@ -138,7 +134,6 @@ object SyncController { new SyncController( appStateStorage, blockchain, - blockchainConfig, syncStateStorage, ledger, validators, diff --git a/src/main/scala/io/iohk/ethereum/blockchain/sync/fast/FastSync.scala b/src/main/scala/io/iohk/ethereum/blockchain/sync/fast/FastSync.scala index b499db376f..cfa7514d46 100644 --- a/src/main/scala/io/iohk/ethereum/blockchain/sync/fast/FastSync.scala +++ b/src/main/scala/io/iohk/ethereum/blockchain/sync/fast/FastSync.scala @@ -22,6 +22,7 @@ import io.iohk.ethereum.domain._ import io.iohk.ethereum.mpt.MerklePatriciaTrie import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo import io.iohk.ethereum.network.Peer +import io.iohk.ethereum.network.p2p.messages.Codes import io.iohk.ethereum.network.p2p.messages.PV62._ import io.iohk.ethereum.network.p2p.messages.PV63._ import io.iohk.ethereum.utils.ByteStringUtils @@ -710,7 +711,7 @@ class FastSync( etcPeerManager, peerEventBus, requestMsg = GetReceipts(receiptsToGet), - responseMsgCode = Receipts.code + responseMsgCode = Codes.ReceiptsCode ) ) @@ -731,7 +732,7 @@ class FastSync( etcPeerManager, peerEventBus, requestMsg = GetBlockBodies(blockBodiesToGet), - responseMsgCode = BlockBodies.code + responseMsgCode = Codes.BlockBodiesCode ) ) @@ -756,7 +757,7 @@ class FastSync( etcPeerManager, peerEventBus, requestMsg = GetBlockHeaders(Left(syncState.bestBlockHeaderNumber + 1), limit, skip = 0, reverse = false), - responseMsgCode = BlockHeaders.code + responseMsgCode = Codes.BlockHeadersCode ), BlockHeadersHandlerName ) diff --git a/src/main/scala/io/iohk/ethereum/blockchain/sync/fast/PivotBlockSelector.scala b/src/main/scala/io/iohk/ethereum/blockchain/sync/fast/PivotBlockSelector.scala index 0a4ce4f282..884116f894 100644 --- a/src/main/scala/io/iohk/ethereum/blockchain/sync/fast/PivotBlockSelector.scala +++ b/src/main/scala/io/iohk/ethereum/blockchain/sync/fast/PivotBlockSelector.scala @@ -8,6 +8,7 @@ import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.MessageFromPeer import io.iohk.ethereum.network.PeerEventBusActor.SubscriptionClassifier.MessageClassifier import io.iohk.ethereum.network.PeerEventBusActor.{PeerSelector, Subscribe, Unsubscribe} +import io.iohk.ethereum.network.p2p.messages.Codes import io.iohk.ethereum.network.p2p.messages.PV62.{BlockHeaders, GetBlockHeaders} import io.iohk.ethereum.network.{EtcPeerManagerActor, Peer, PeerId} import io.iohk.ethereum.utils.Config.SyncConfig @@ -79,7 +80,7 @@ class PivotBlockSelector( ): Receive = handleCommonMessages orElse { case MessageFromPeer(blockHeaders: BlockHeaders, peerId) => - peerEventBus ! Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peerId))) + peerEventBus ! Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peerId))) val updatedPeersToAsk = peersToAsk - peerId val targetBlockHeaderOpt = if (blockHeaders.headers.size != 1) None @@ -167,7 +168,7 @@ class PivotBlockSelector( } private def obtainBlockHeaderFromPeer(peer: PeerId, blockNumber: BigInt): Unit = { - peerEventBus ! Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer))) + peerEventBus ! Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer))) etcPeerManager ! EtcPeerManagerActor.SendMessage( GetBlockHeaders(Left(blockNumber), 1, 0, reverse = false), peer diff --git a/src/main/scala/io/iohk/ethereum/blockchain/sync/fast/SyncStateSchedulerActor.scala b/src/main/scala/io/iohk/ethereum/blockchain/sync/fast/SyncStateSchedulerActor.scala index c91087126f..4c79ca9f19 100644 --- a/src/main/scala/io/iohk/ethereum/blockchain/sync/fast/SyncStateSchedulerActor.scala +++ b/src/main/scala/io/iohk/ethereum/blockchain/sync/fast/SyncStateSchedulerActor.scala @@ -15,6 +15,7 @@ import io.iohk.ethereum.blockchain.sync.fast.SyncStateScheduler.{ import io.iohk.ethereum.blockchain.sync.fast.SyncStateSchedulerActor._ import io.iohk.ethereum.blockchain.sync.{BlacklistSupport, PeerListSupport, PeerRequestHandler} import io.iohk.ethereum.network.Peer +import io.iohk.ethereum.network.p2p.messages.Codes import io.iohk.ethereum.network.p2p.messages.PV63.{GetNodeData, NodeData} import io.iohk.ethereum.utils.ByteStringUtils import io.iohk.ethereum.utils.Config.SyncConfig @@ -55,7 +56,7 @@ class SyncStateSchedulerActor( etcPeerManager, peerEventBus, requestMsg = GetNodeData(request.nodes.toList), - responseMsgCode = NodeData.code + responseMsgCode = Codes.NodeDataCode ) ) context.watchWith(handler, RequestTerminated(request.peer)) diff --git a/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockBroadcast.scala b/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockBroadcast.scala index 536684a8a0..eec69f3315 100644 --- a/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockBroadcast.scala +++ b/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockBroadcast.scala @@ -1,10 +1,12 @@ package io.iohk.ethereum.blockchain.sync.regular import akka.actor.ActorRef +import io.iohk.ethereum.blockchain.sync.regular.BlockBroadcast.BlockToBroadcast +import io.iohk.ethereum.domain.{Block, ChainWeight} import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo -import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock -import io.iohk.ethereum.network.p2p.messages.PV62 +import io.iohk.ethereum.network.p2p.MessageSerializable import io.iohk.ethereum.network.p2p.messages.PV62.BlockHash +import io.iohk.ethereum.network.p2p.messages.{CommonMessages, PV62, PV64, ProtocolVersions} import io.iohk.ethereum.network.{EtcPeerManagerActor, Peer} import io.iohk.ethereum.utils.Config.SyncConfig @@ -18,35 +20,39 @@ class BlockBroadcast(val etcPeerManager: ActorRef, syncConfig: SyncConfig) { * The hash of the block is sent to all of those peers while the block itself is only sent to * the square root of the total number of those peers, with the subset being obtained randomly. * - * @param newBlock, block to broadcast + * @param blockToBroadcast, block to broadcast * @param handshakedPeers, to which the blocks will be broadcasted to */ - def broadcastBlock(newBlock: NewBlock, handshakedPeers: Map[Peer, PeerInfo]): Unit = { - val peersWithoutBlock = handshakedPeers.collect { - case (peer, peerInfo) if shouldSendNewBlock(newBlock, peerInfo) => peer - }.toSet + def broadcastBlock(blockToBroadcast: BlockToBroadcast, handshakedPeers: Map[Peer, PeerInfo]): Unit = { + val peersWithoutBlock = handshakedPeers.filter { case (_, peerInfo) => + shouldSendNewBlock(blockToBroadcast, peerInfo) + } - broadcastNewBlock(newBlock, peersWithoutBlock) + broadcastNewBlock(blockToBroadcast, peersWithoutBlock) if (syncConfig.broadcastNewBlockHashes) { // NOTE: the usefulness of this message is debatable, especially in private networks - broadcastNewBlockHash(newBlock, peersWithoutBlock) + broadcastNewBlockHash(blockToBroadcast, peersWithoutBlock.keySet) } } - private def shouldSendNewBlock(newBlock: NewBlock, peerInfo: PeerInfo): Boolean = + private def shouldSendNewBlock(newBlock: BlockToBroadcast, peerInfo: PeerInfo): Boolean = newBlock.block.header.number > peerInfo.maxBlockNumber || newBlock.chainWeight > peerInfo.chainWeight - private def broadcastNewBlock(newBlock: NewBlock, peers: Set[Peer]): Unit = - obtainRandomPeerSubset(peers).foreach { peer => - etcPeerManager ! EtcPeerManagerActor.SendMessage(newBlock, peer.id) + private def broadcastNewBlock(blockToBroadcast: BlockToBroadcast, peers: Map[Peer, PeerInfo]): Unit = + obtainRandomPeerSubset(peers.keySet).foreach { peer => + val message: MessageSerializable = + if (peers(peer).remoteStatus.protocolVersion == ProtocolVersions.PV64) blockToBroadcast.as64 + else blockToBroadcast.as63 + etcPeerManager ! EtcPeerManagerActor.SendMessage(message, peer.id) } - private def broadcastNewBlockHash(newBlock: NewBlock, peers: Set[Peer]): Unit = peers.foreach { peer => - val newBlockHeader = newBlock.block.header - val newBlockHashMsg = PV62.NewBlockHashes(Seq(BlockHash(newBlockHeader.hash, newBlockHeader.number))) - etcPeerManager ! EtcPeerManagerActor.SendMessage(newBlockHashMsg, peer.id) + private def broadcastNewBlockHash(blockToBroadcast: BlockToBroadcast, peers: Set[Peer]): Unit = peers.foreach { + peer => + val newBlockHeader = blockToBroadcast.block.header + val newBlockHashMsg = PV62.NewBlockHashes(Seq(BlockHash(newBlockHeader.hash, newBlockHeader.number))) + etcPeerManager ! EtcPeerManagerActor.SendMessage(newBlockHashMsg, peer.id) } /** @@ -61,3 +67,15 @@ class BlockBroadcast(val etcPeerManager: ActorRef, syncConfig: SyncConfig) { Random.shuffle(peers).take(numberOfPeersToSend) } } + +object BlockBroadcast { + + /** + * BlockToBroadcast was created to decouple block information from protocol new block messages + * (they are different versions of NewBlock msg) + */ + case class BlockToBroadcast(block: Block, chainWeight: ChainWeight) { + def as63: CommonMessages.NewBlock = CommonMessages.NewBlock(block, chainWeight.totalDifficulty) + def as64: PV64.NewBlock = PV64.NewBlock(block, chainWeight) + } +} diff --git a/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockBroadcasterActor.scala b/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockBroadcasterActor.scala index 560d70cda6..cd4243faa7 100644 --- a/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockBroadcasterActor.scala +++ b/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockBroadcasterActor.scala @@ -1,8 +1,8 @@ package io.iohk.ethereum.blockchain.sync.regular import akka.actor.{Actor, ActorLogging, ActorRef, Props, Scheduler} +import io.iohk.ethereum.blockchain.sync.regular.BlockBroadcast.BlockToBroadcast import io.iohk.ethereum.blockchain.sync.{BlacklistSupport, PeerListSupport} -import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock import io.iohk.ethereum.utils.Config.SyncConfig class BlockBroadcasterActor( @@ -26,8 +26,8 @@ class BlockBroadcasterActor( } object BlockBroadcasterActor { sealed trait BroadcasterMsg - case class BroadcastBlock(block: NewBlock) extends BroadcasterMsg - case class BroadcastBlocks(blocks: List[NewBlock]) extends BroadcasterMsg + case class BroadcastBlock(block: BlockToBroadcast) extends BroadcasterMsg + case class BroadcastBlocks(blocks: List[BlockToBroadcast]) extends BroadcasterMsg def props( broadcast: BlockBroadcast, diff --git a/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockFetcher.scala b/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockFetcher.scala index 635cf01306..2f3bb769b8 100644 --- a/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockFetcher.scala +++ b/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockFetcher.scala @@ -21,7 +21,8 @@ import io.iohk.ethereum.domain._ import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.MessageFromPeer import io.iohk.ethereum.network.PeerEventBusActor.SubscriptionClassifier.MessageClassifier import io.iohk.ethereum.network.PeerEventBusActor.{PeerSelector, Subscribe, Unsubscribe} -import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock +import io.iohk.ethereum.network.PeerId +import io.iohk.ethereum.network.p2p.messages.{Codes, CommonMessages, PV64} import io.iohk.ethereum.network.p2p.messages.PV62._ import io.iohk.ethereum.network.p2p.messages.PV63.{GetNodeData, NodeData} import io.iohk.ethereum.utils.ByteStringUtils @@ -59,7 +60,7 @@ class BlockFetcher( BlockFetcherState.initial(importer, blockValidator, blockNr) |> fetchBlocks peerEventBus ! Subscribe( MessageClassifier( - Set(NewBlock.code63, NewBlock.code64, NewBlockHashes.code, BlockHeaders.code), + Set(Codes.NewBlockCode, Codes.NewBlockHashesCode, Codes.BlockHeadersCode), PeerSelector.AllPeers ) ) @@ -198,31 +199,37 @@ class BlockFetcher( } supervisor ! ProgressProtocol.GotNewBlock(newState.knownTop) fetchBlocks(newState) - case MessageFromPeer(NewBlock(_, block, _), peerId) => - //TODO ETCM-389: Handle mined, checkpoint and new blocks uniformly - log.debug("Received NewBlock {}", block.idTag) - val newBlockNr = block.number - val nextExpectedBlock = state.lastBlock + 1 - - if (state.isOnTop && newBlockNr == nextExpectedBlock) { - log.debug("Passing block directly to importer") - val newState = state.withPeerForBlocks(peerId, Seq(newBlockNr)).withKnownTopAt(newBlockNr) - state.importer ! OnTop - state.importer ! ImportNewBlock(block, peerId) - supervisor ! ProgressProtocol.GotNewBlock(newState.knownTop) - context become started(newState) - } else { - log.debug("Ignoring received block as it doesn't match local state or fetch side is not on top") - val newState = state.withPossibleNewTopAt(block.number) - supervisor ! ProgressProtocol.GotNewBlock(newState.knownTop) - fetchBlocks(newState) - } + case MessageFromPeer(CommonMessages.NewBlock(block, _), peerId) => + handleNewBlock(block, peerId, state) + case MessageFromPeer(PV64.NewBlock(block, _), peerId) => + handleNewBlock(block, peerId, state) case BlockImportFailed(blockNr, reason) => val (peerId, newState) = state.invalidateBlocksFrom(blockNr) peerId.foreach(id => peersClient ! BlacklistPeer(id, reason)) fetchBlocks(newState) } + private def handleNewBlock(block: Block, peerId: PeerId, state: BlockFetcherState): Unit = { + //TODO ETCM-389: Handle mined, checkpoint and new blocks uniformly + log.debug("Received NewBlock {}", block.idTag) + val newBlockNr = block.number + val nextExpectedBlock = state.lastBlock + 1 + + if (state.isOnTop && newBlockNr == nextExpectedBlock) { + log.debug("Passing block directly to importer") + val newState = state.withPeerForBlocks(peerId, Seq(newBlockNr)).withKnownTopAt(newBlockNr) + state.importer ! OnTop + state.importer ! ImportNewBlock(block, peerId) + supervisor ! ProgressProtocol.GotNewBlock(newState.knownTop) + context become started(newState) + } else { + log.debug("Ignoring received block as it doesn't match local state or fetch side is not on top") + val newState = state.withPossibleNewTopAt(block.number) + supervisor ! ProgressProtocol.GotNewBlock(newState.knownTop) + fetchBlocks(newState) + } + } + private def handlePossibleTopUpdate(state: BlockFetcherState): Receive = { //by handling these type of messages, fetcher can received from network, fresh info about blocks on top //ex. After a successful handshake, fetcher will receive the info about the header of the peer best block diff --git a/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockImporter.scala b/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockImporter.scala index 4c8352fecd..78ed13acac 100644 --- a/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockImporter.scala +++ b/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockImporter.scala @@ -5,6 +5,7 @@ import akka.actor.{Actor, ActorLogging, ActorRef, NotInfluenceReceiveTimeout, Pr import akka.util.ByteString import cats.data.NonEmptyList import cats.implicits._ +import io.iohk.ethereum.blockchain.sync.regular.BlockBroadcast.BlockToBroadcast import io.iohk.ethereum.blockchain.sync.regular.BlockBroadcasterActor.BroadcastBlocks import io.iohk.ethereum.blockchain.sync.regular.RegularSync.ProgressProtocol import io.iohk.ethereum.consensus.blocks.CheckpointBlockGenerator @@ -13,13 +14,12 @@ import io.iohk.ethereum.domain._ import io.iohk.ethereum.ledger._ import io.iohk.ethereum.mpt.MerklePatriciaTrie.MissingNodeException import io.iohk.ethereum.network.PeerId -import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock import io.iohk.ethereum.ommers.OmmersPool.AddOmmers import io.iohk.ethereum.transactions.PendingTransactionsManager import io.iohk.ethereum.transactions.PendingTransactionsManager.{AddUncheckedTransactions, RemoveTransactions} +import io.iohk.ethereum.utils.ByteStringUtils import io.iohk.ethereum.utils.Config.SyncConfig import io.iohk.ethereum.utils.FunctorOps._ -import io.iohk.ethereum.utils.{BlockchainConfig, ByteStringUtils} import scala.concurrent.duration._ import scala.concurrent.{ExecutionContext, Future} @@ -30,7 +30,6 @@ class BlockImporter( fetcher: ActorRef, ledger: Ledger, blockchain: Blockchain, - blockchainConfig: BlockchainConfig, //FIXME: this should not be needed after ETCM-280 syncConfig: SyncConfig, ommersPool: ActorRef, broadcaster: ActorRef, @@ -283,16 +282,10 @@ class BlockImporter( } private def broadcastBlocks(blocks: List[Block], weights: List[ChainWeight]): Unit = { - val newBlocks = (blocks, weights).mapN(NewBlock(_, _)).map { nb => - if (nb.block.number < blockchainConfig.ecip1097BlockNumber) nb.as63 else nb.as64 - } - - //TODO: use the target PeerInfo to determine code and encoding when sending the message: ETCM-280 - broadcastNewBlocks(newBlocks) + val newBlocks = (blocks, weights).mapN(BlockToBroadcast(_, _)) + broadcaster ! BroadcastBlocks(newBlocks) } - private def broadcastNewBlocks(blocks: List[NewBlock]): Unit = broadcaster ! BroadcastBlocks(blocks) - private def updateTxPool(blocksAdded: Seq[Block], blocksRemoved: Seq[Block]): Unit = { blocksRemoved.foreach(block => pendingTransactionsManager ! AddUncheckedTransactions(block.body.transactionList)) blocksAdded.foreach { block => @@ -354,7 +347,6 @@ object BlockImporter { fetcher: ActorRef, ledger: Ledger, blockchain: Blockchain, - blockchainConfig: BlockchainConfig, syncConfig: SyncConfig, ommersPool: ActorRef, broadcaster: ActorRef, @@ -367,7 +359,6 @@ object BlockImporter { fetcher, ledger, blockchain, - blockchainConfig, syncConfig, ommersPool, broadcaster, diff --git a/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSync.scala b/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSync.scala index 2bbf4abd8c..4fe2ef4290 100644 --- a/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSync.scala +++ b/src/main/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSync.scala @@ -5,14 +5,14 @@ import akka.util.ByteString import io.iohk.ethereum.blockchain.sync.SyncProtocol import io.iohk.ethereum.blockchain.sync.SyncProtocol.Status import io.iohk.ethereum.blockchain.sync.SyncProtocol.Status.Progress -import io.iohk.ethereum.blockchain.sync.regular.RegularSync.{NewCheckpoint, ProgressProtocol, ProgressState} import io.iohk.ethereum.blockchain.sync.regular.BlockFetcher.InternalLastBlockImport +import io.iohk.ethereum.blockchain.sync.regular.RegularSync.{NewCheckpoint, ProgressProtocol, ProgressState} import io.iohk.ethereum.consensus.blocks.CheckpointBlockGenerator import io.iohk.ethereum.consensus.validators.BlockValidator import io.iohk.ethereum.crypto.ECDSASignature import io.iohk.ethereum.domain.Blockchain import io.iohk.ethereum.ledger.Ledger -import io.iohk.ethereum.utils.{BlockchainConfig, ByteStringUtils} +import io.iohk.ethereum.utils.ByteStringUtils import io.iohk.ethereum.utils.Config.SyncConfig class RegularSync( @@ -21,7 +21,6 @@ class RegularSync( peerEventBus: ActorRef, ledger: Ledger, blockchain: Blockchain, - blockchainConfig: BlockchainConfig, blockValidator: BlockValidator, syncConfig: SyncConfig, ommersPool: ActorRef, @@ -47,7 +46,6 @@ class RegularSync( fetcher, ledger, blockchain, - blockchainConfig, syncConfig, ommersPool, broadcaster, @@ -125,7 +123,6 @@ object RegularSync { peerEventBus: ActorRef, ledger: Ledger, blockchain: Blockchain, - blockchainConfig: BlockchainConfig, blockValidator: BlockValidator, syncConfig: SyncConfig, ommersPool: ActorRef, @@ -140,7 +137,6 @@ object RegularSync { peerEventBus, ledger, blockchain, - blockchainConfig, blockValidator, syncConfig, ommersPool, diff --git a/src/main/scala/io/iohk/ethereum/network/EtcPeerManagerActor.scala b/src/main/scala/io/iohk/ethereum/network/EtcPeerManagerActor.scala index 071d8cc8de..3a348e0e9e 100644 --- a/src/main/scala/io/iohk/ethereum/network/EtcPeerManagerActor.scala +++ b/src/main/scala/io/iohk/ethereum/network/EtcPeerManagerActor.scala @@ -4,16 +4,17 @@ import akka.actor.{Actor, ActorLogging, ActorRef, Props} import akka.util.ByteString import io.iohk.ethereum.db.storage.AppStateStorage import io.iohk.ethereum.domain.ChainWeight -import io.iohk.ethereum.network.PeerActor.{DisconnectPeer, SendMessage} import io.iohk.ethereum.network.EtcPeerManagerActor._ -import io.iohk.ethereum.network.PeerEventBusActor.{PeerSelector, Subscribe, Unsubscribe} +import io.iohk.ethereum.network.PeerActor.{DisconnectPeer, SendMessage} import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent._ import io.iohk.ethereum.network.PeerEventBusActor.SubscriptionClassifier._ +import io.iohk.ethereum.network.PeerEventBusActor.{PeerSelector, Subscribe, Unsubscribe} import io.iohk.ethereum.network.handshaker.Handshaker.HandshakeResult -import io.iohk.ethereum.network.p2p.{Message, MessageSerializable} -import io.iohk.ethereum.network.p2p.messages.CommonMessages.{NewBlock, Status} import io.iohk.ethereum.network.p2p.messages.PV62.{BlockHeaders, GetBlockHeaders, NewBlockHashes} +import io.iohk.ethereum.network.p2p.messages.PV64.NewBlock import io.iohk.ethereum.network.p2p.messages.WireProtocol.Disconnect +import io.iohk.ethereum.network.p2p.messages.{Codes, CommonMessages, PV64} +import io.iohk.ethereum.network.p2p.{Message, MessageSerializable} import io.iohk.ethereum.utils.ByteStringUtils /** @@ -158,7 +159,9 @@ class EtcPeerManagerActor( */ private def updateChainWeight(message: Message)(initialPeerInfo: PeerInfo): PeerInfo = message match { - case newBlock: NewBlock => initialPeerInfo.copy(chainWeight = newBlock.chainWeight) + case newBlock: CommonMessages.NewBlock => + initialPeerInfo.copy(chainWeight = ChainWeight.totalDifficultyOnly(newBlock.totalDifficulty)) + case newBlock: PV64.NewBlock => initialPeerInfo.copy(chainWeight = newBlock.chainWeight) case _ => initialPeerInfo } @@ -217,6 +220,8 @@ class EtcPeerManagerActor( message match { case m: BlockHeaders => update(m.headers.map(header => (header.number, header.hash))) + case m: CommonMessages.NewBlock => + update(Seq((m.block.header.number, m.block.header.hash))) case m: NewBlock => update(Seq((m.block.header.number, m.block.header.hash))) case m: NewBlockHashes => @@ -229,10 +234,48 @@ class EtcPeerManagerActor( object EtcPeerManagerActor { - val msgCodesWithInfo: Set[Int] = Set(BlockHeaders.code, NewBlock.code63, NewBlock.code64, NewBlockHashes.code) + val msgCodesWithInfo: Set[Int] = Set(Codes.BlockHeadersCode, Codes.NewBlockCode, Codes.NewBlockHashesCode) + + /** + * RemoteStatus was created to decouple status information from protocol status messages + * (they are different versions of Status msg) + */ + case class RemoteStatus( + protocolVersion: Int, + networkId: Int, + chainWeight: ChainWeight, + bestHash: ByteString, + genesisHash: ByteString + ) { + override def toString: String = { + s"RemoteStatus { " + + s"protocolVersion: $protocolVersion, " + + s"networkId: $networkId, " + + s"chainWeight: $chainWeight, " + + s"bestHash: ${ByteStringUtils.hash2string(bestHash)}, " + + s"genesisHash: ${ByteStringUtils.hash2string(genesisHash)}," + + s"}" + } + } + + object RemoteStatus { + def apply(status: PV64.Status): RemoteStatus = { + RemoteStatus(status.protocolVersion, status.networkId, status.chainWeight, status.bestHash, status.genesisHash) + } + + def apply(status: CommonMessages.Status): RemoteStatus = { + RemoteStatus( + status.protocolVersion, + status.networkId, + ChainWeight.totalDifficultyOnly(status.totalDifficulty), + status.bestHash, + status.genesisHash + ) + } + } case class PeerInfo( - remoteStatus: Status, // Updated only after handshaking + remoteStatus: RemoteStatus, // Updated only after handshaking chainWeight: ChainWeight, forkAccepted: Boolean, maxBlockNumber: BigInt, @@ -258,7 +301,7 @@ object EtcPeerManagerActor { } object PeerInfo { - def apply(remoteStatus: Status, forkAccepted: Boolean): PeerInfo = { + def apply(remoteStatus: RemoteStatus, forkAccepted: Boolean): PeerInfo = { PeerInfo( remoteStatus, remoteStatus.chainWeight, @@ -268,9 +311,11 @@ object EtcPeerManagerActor { ) } - def withForkAccepted(remoteStatus: Status): PeerInfo = PeerInfo(remoteStatus, forkAccepted = true) + def withForkAccepted(remoteStatus: RemoteStatus): PeerInfo = + PeerInfo(remoteStatus, forkAccepted = true) - def withNotForkAccepted(remoteStatus: Status): PeerInfo = PeerInfo(remoteStatus, forkAccepted = false) + def withNotForkAccepted(remoteStatus: RemoteStatus): PeerInfo = + PeerInfo(remoteStatus, forkAccepted = false) } private case class PeerWithInfo(peer: Peer, peerInfo: PeerInfo) diff --git a/src/main/scala/io/iohk/ethereum/network/PeerActor.scala b/src/main/scala/io/iohk/ethereum/network/PeerActor.scala index 09a10c6804..bb53d1a961 100644 --- a/src/main/scala/io/iohk/ethereum/network/PeerActor.scala +++ b/src/main/scala/io/iohk/ethereum/network/PeerActor.scala @@ -12,8 +12,8 @@ import io.iohk.ethereum.network.PeerManagerActor.PeerConfiguration import io.iohk.ethereum.network.handshaker.Handshaker import io.iohk.ethereum.network.handshaker.Handshaker.HandshakeComplete.{HandshakeFailure, HandshakeSuccess} import io.iohk.ethereum.network.handshaker.Handshaker.{HandshakeResult, NextMessage} +import io.iohk.ethereum.network.p2p.Message.Version import io.iohk.ethereum.network.p2p._ -import io.iohk.ethereum.network.p2p.messages.Versions import io.iohk.ethereum.network.p2p.messages.WireProtocol._ import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler.RLPxConfiguration import io.iohk.ethereum.network.rlpx.{AuthHandshaker, RLPxConnectionHandler} @@ -276,6 +276,7 @@ class PeerActor[R <: HandshakeResult]( } object PeerActor { + // scalastyle:off parameter.number def props[R <: HandshakeResult]( peerAddress: InetSocketAddress, peerConfiguration: PeerConfiguration, @@ -284,12 +285,13 @@ object PeerActor { incomingConnection: Boolean, handshaker: Handshaker[R], authHandshaker: AuthHandshaker, - messageDecoder: MessageDecoder + messageDecoder: MessageDecoder, + bestProtocolVersion: Version ): Props = Props( new PeerActor( peerAddress, - rlpxConnectionFactory(authHandshaker, messageDecoder, peerConfiguration.rlpxConfiguration), + rlpxConnectionFactory(authHandshaker, messageDecoder, peerConfiguration.rlpxConfiguration, bestProtocolVersion), peerConfiguration, peerEventBus, knownNodesManager, @@ -297,15 +299,17 @@ object PeerActor { initHandshaker = handshaker ) ) + // scalastyle:on parameter.number def rlpxConnectionFactory( authHandshaker: AuthHandshaker, messageDecoder: MessageDecoder, - rlpxConfiguration: RLPxConfiguration + rlpxConfiguration: RLPxConfiguration, + bestProtocolVersion: Version ): ActorContext => ActorRef = { ctx => ctx.actorOf( RLPxConnectionHandler - .props(NetworkMessageDecoder orElse messageDecoder, Versions.PV63, authHandshaker, rlpxConfiguration), + .props(NetworkMessageDecoder orElse messageDecoder, bestProtocolVersion, authHandshaker, rlpxConfiguration), "rlpx-connection" ) } diff --git a/src/main/scala/io/iohk/ethereum/network/PeerManagerActor.scala b/src/main/scala/io/iohk/ethereum/network/PeerManagerActor.scala index 445018dff1..71517ea040 100644 --- a/src/main/scala/io/iohk/ethereum/network/PeerManagerActor.scala +++ b/src/main/scala/io/iohk/ethereum/network/PeerManagerActor.scala @@ -14,6 +14,7 @@ import io.iohk.ethereum.network.PeerManagerActor.PeerConfiguration import io.iohk.ethereum.network.discovery.{DiscoveryConfig, PeerDiscoveryManager} import io.iohk.ethereum.network.handshaker.Handshaker import io.iohk.ethereum.network.handshaker.Handshaker.HandshakeResult +import io.iohk.ethereum.network.p2p.Message.Version import io.iohk.ethereum.network.p2p.messages.WireProtocol.Disconnect import io.iohk.ethereum.network.p2p.{MessageDecoder, MessageSerializable} import io.iohk.ethereum.network.rlpx.AuthHandshaker @@ -292,6 +293,7 @@ class PeerManagerActor( } object PeerManagerActor { + // scalastyle:off parameter.number def props[R <: HandshakeResult]( peerDiscoveryManager: ActorRef, peerConfiguration: PeerConfiguration, @@ -300,10 +302,19 @@ object PeerManagerActor { handshaker: Handshaker[R], authHandshaker: AuthHandshaker, messageDecoder: MessageDecoder, - discoveryConfig: DiscoveryConfig + discoveryConfig: DiscoveryConfig, + bestProtocolVersion: Version ): Props = { val factory: (ActorContext, InetSocketAddress, Boolean) => ActorRef = - peerFactory(peerConfiguration, peerMessageBus, knownNodesManager, handshaker, authHandshaker, messageDecoder) + peerFactory( + peerConfiguration, + peerMessageBus, + knownNodesManager, + handshaker, + authHandshaker, + messageDecoder, + bestProtocolVersion + ) Props( new PeerManagerActor( @@ -316,6 +327,7 @@ object PeerManagerActor { ) ) } + // scalastyle:on parameter.number def peerFactory[R <: HandshakeResult]( config: PeerConfiguration, @@ -323,7 +335,8 @@ object PeerManagerActor { knownNodesManager: ActorRef, handshaker: Handshaker[R], authHandshaker: AuthHandshaker, - messageDecoder: MessageDecoder + messageDecoder: MessageDecoder, + bestProtocolVersion: Version ): (ActorContext, InetSocketAddress, Boolean) => ActorRef = { (ctx, address, incomingConnection) => val id: String = address.toString.filterNot(_ == '/') val props = PeerActor.props( @@ -334,7 +347,8 @@ object PeerManagerActor { incomingConnection, handshaker, authHandshaker, - messageDecoder + messageDecoder, + bestProtocolVersion ) ctx.actorOf(props, id) } diff --git a/src/main/scala/io/iohk/ethereum/network/handshaker/EtcForkBlockExchangeState.scala b/src/main/scala/io/iohk/ethereum/network/handshaker/EtcForkBlockExchangeState.scala index 1d2e0734f7..74b6969dc6 100644 --- a/src/main/scala/io/iohk/ethereum/network/handshaker/EtcForkBlockExchangeState.scala +++ b/src/main/scala/io/iohk/ethereum/network/handshaker/EtcForkBlockExchangeState.scala @@ -1,18 +1,17 @@ package io.iohk.ethereum.network.handshaker +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} import io.iohk.ethereum.network.ForkResolver -import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo import io.iohk.ethereum.network.handshaker.Handshaker.NextMessage -import io.iohk.ethereum.network.p2p.{Message, MessageSerializable} -import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status import io.iohk.ethereum.network.p2p.messages.PV62.{BlockHeaders, GetBlockHeaders} import io.iohk.ethereum.network.p2p.messages.WireProtocol.Disconnect +import io.iohk.ethereum.network.p2p.{Message, MessageSerializable} import io.iohk.ethereum.utils.Logger case class EtcForkBlockExchangeState( handshakerConfiguration: EtcHandshakerConfiguration, forkResolver: ForkResolver, - remoteStatus: Status + remoteStatus: RemoteStatus ) extends InProgressState[PeerInfo] with Logger { diff --git a/src/main/scala/io/iohk/ethereum/network/handshaker/EtcHandshaker.scala b/src/main/scala/io/iohk/ethereum/network/handshaker/EtcHandshaker.scala index 9fa1820bf7..f63a0fca82 100644 --- a/src/main/scala/io/iohk/ethereum/network/handshaker/EtcHandshaker.scala +++ b/src/main/scala/io/iohk/ethereum/network/handshaker/EtcHandshaker.scala @@ -1,12 +1,13 @@ package io.iohk.ethereum.network.handshaker +import java.util.concurrent.atomic.AtomicReference + import io.iohk.ethereum.db.storage.AppStateStorage import io.iohk.ethereum.domain.Blockchain +import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo import io.iohk.ethereum.network.ForkResolver import io.iohk.ethereum.network.PeerManagerActor.PeerConfiguration -import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo -import io.iohk.ethereum.utils.{BlockchainConfig, NodeStatus} -import java.util.concurrent.atomic.AtomicReference +import io.iohk.ethereum.utils.NodeStatus case class EtcHandshaker private ( handshakerState: HandshakerState[PeerInfo], @@ -31,8 +32,8 @@ object EtcHandshaker { trait EtcHandshakerConfiguration { val nodeStatusHolder: AtomicReference[NodeStatus] val blockchain: Blockchain - val blockchainConfig: BlockchainConfig val appStateStorage: AppStateStorage val peerConfiguration: PeerConfiguration val forkResolverOpt: Option[ForkResolver] + val protocolVersion: Int } diff --git a/src/main/scala/io/iohk/ethereum/network/handshaker/EtcHelloExchangeState.scala b/src/main/scala/io/iohk/ethereum/network/handshaker/EtcHelloExchangeState.scala index c902f4e6b6..d33a14d4cc 100644 --- a/src/main/scala/io/iohk/ethereum/network/handshaker/EtcHelloExchangeState.scala +++ b/src/main/scala/io/iohk/ethereum/network/handshaker/EtcHelloExchangeState.scala @@ -4,8 +4,10 @@ import akka.util.ByteString import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo import io.iohk.ethereum.network.handshaker.Handshaker.NextMessage import io.iohk.ethereum.network.p2p.Message -import io.iohk.ethereum.network.p2p.messages.Versions -import io.iohk.ethereum.network.p2p.messages.WireProtocol.{Capability, Disconnect, Hello} +import io.iohk.ethereum.network.p2p.messages.Capability.Capabilities +import io.iohk.ethereum.network.p2p.messages.Capability.Capabilities._ +import io.iohk.ethereum.network.p2p.messages.ProtocolVersions +import io.iohk.ethereum.network.p2p.messages.WireProtocol.{Disconnect, Hello} import io.iohk.ethereum.utils.{Config, Logger, ServerStatus} case class EtcHelloExchangeState(handshakerConfiguration: EtcHandshakerConfiguration) @@ -24,10 +26,16 @@ case class EtcHelloExchangeState(handshakerConfiguration: EtcHandshakerConfigura override def applyResponseMessage: PartialFunction[Message, HandshakerState[PeerInfo]] = { case hello: Hello => log.debug("Protocol handshake finished with peer ({})", hello) - if (hello.capabilities.contains(Capability("eth", Versions.PV63.toByte))) - EtcNodeStatusExchangeState(handshakerConfiguration) + if ( + handshakerConfiguration.protocolVersion == ProtocolVersions.PV64 && hello.capabilities.contains(Etc64Capability) + ) + EtcNodeStatus64ExchangeState(handshakerConfiguration) + else if (hello.capabilities.contains(Eth63Capability)) + EtcNodeStatus63ExchangeState(handshakerConfiguration) else { - log.debug("Connected peer does not support eth {} protocol. Disconnecting.", Versions.PV63.toByte) + log.debug( + s"Connected peer does not support eth ${ProtocolVersions.PV63.toByte} / ${ProtocolVersions.PV64.toByte} protocol. Disconnecting." + ) DisconnectedState(Disconnect.Reasons.IncompatibleP2pProtocolVersion) } @@ -44,10 +52,13 @@ case class EtcHelloExchangeState(handshakerConfiguration: EtcHandshakerConfigura case ServerStatus.Listening(address) => address.getPort case ServerStatus.NotListening => 0 } + val capabilities = + if (handshakerConfiguration.protocolVersion == ProtocolVersions.PV64) Capabilities.All else Seq(Eth63Capability) + Hello( p2pVersion = EtcHelloExchangeState.P2pVersion, clientId = Config.clientId, - capabilities = Seq(Capability("eth", Versions.PV63.toByte)), + capabilities = capabilities, listenPort = listenPort, nodeId = ByteString(nodeStatus.nodeId) ) diff --git a/src/main/scala/io/iohk/ethereum/network/handshaker/EtcNodeStatus63ExchangeState.scala b/src/main/scala/io/iohk/ethereum/network/handshaker/EtcNodeStatus63ExchangeState.scala new file mode 100644 index 0000000000..d1614655fb --- /dev/null +++ b/src/main/scala/io/iohk/ethereum/network/handshaker/EtcNodeStatus63ExchangeState.scala @@ -0,0 +1,34 @@ +package io.iohk.ethereum.network.handshaker + +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} +import io.iohk.ethereum.network.p2p.messages.{CommonMessages, ProtocolVersions} +import io.iohk.ethereum.network.p2p.{Message, MessageSerializable} + +case class EtcNodeStatus63ExchangeState( + handshakerConfiguration: EtcHandshakerConfiguration +) extends EtcNodeStatusExchangeState[CommonMessages.Status] { + + import handshakerConfiguration._ + + def applyResponseMessage: PartialFunction[Message, HandshakerState[PeerInfo]] = { + case status: CommonMessages.Status => + applyRemoteStatusMessage(RemoteStatus(status)) + } + + override protected def createStatusMsg(): MessageSerializable = { + val bestBlockHeader = getBestBlockHeader() + val chainWeight = blockchain.getChainWeightByHash(bestBlockHeader.hash).get + + val status = CommonMessages.Status( + protocolVersion = ProtocolVersions.PV63, + networkId = peerConfiguration.networkId, + totalDifficulty = chainWeight.totalDifficulty, + bestHash = bestBlockHeader.hash, + genesisHash = blockchain.genesisHeader.hash + ) + + log.debug(s"sending status $status") + status + } + +} diff --git a/src/main/scala/io/iohk/ethereum/network/handshaker/EtcNodeStatus64ExchangeState.scala b/src/main/scala/io/iohk/ethereum/network/handshaker/EtcNodeStatus64ExchangeState.scala new file mode 100644 index 0000000000..837c8b9e37 --- /dev/null +++ b/src/main/scala/io/iohk/ethereum/network/handshaker/EtcNodeStatus64ExchangeState.scala @@ -0,0 +1,33 @@ +package io.iohk.ethereum.network.handshaker + +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} +import io.iohk.ethereum.network.p2p.messages.{PV64, ProtocolVersions} +import io.iohk.ethereum.network.p2p.{Message, MessageSerializable} + +case class EtcNodeStatus64ExchangeState( + handshakerConfiguration: EtcHandshakerConfiguration +) extends EtcNodeStatusExchangeState[PV64.Status] { + + import handshakerConfiguration._ + + def applyResponseMessage: PartialFunction[Message, HandshakerState[PeerInfo]] = { case status: PV64.Status => + applyRemoteStatusMessage(RemoteStatus(status)) + } + + override protected def createStatusMsg(): MessageSerializable = { + val bestBlockHeader = getBestBlockHeader() + val chainWeight = blockchain.getChainWeightByHash(bestBlockHeader.hash).get + + val status = PV64.Status( + protocolVersion = ProtocolVersions.PV64, + networkId = peerConfiguration.networkId, + chainWeight = chainWeight, + bestHash = bestBlockHeader.hash, + genesisHash = blockchain.genesisHeader.hash + ) + + log.debug(s"sending status $status") + status + } + +} diff --git a/src/main/scala/io/iohk/ethereum/network/handshaker/EtcNodeStatusExchangeState.scala b/src/main/scala/io/iohk/ethereum/network/handshaker/EtcNodeStatusExchangeState.scala index 0d29b40ec7..e764320a5d 100644 --- a/src/main/scala/io/iohk/ethereum/network/handshaker/EtcNodeStatusExchangeState.scala +++ b/src/main/scala/io/iohk/ethereum/network/handshaker/EtcNodeStatusExchangeState.scala @@ -1,17 +1,15 @@ package io.iohk.ethereum.network.handshaker -import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} import io.iohk.ethereum.network.handshaker.Handshaker.NextMessage -import io.iohk.ethereum.network.p2p.Message -import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status -import io.iohk.ethereum.network.p2p.messages.Versions import io.iohk.ethereum.network.p2p.messages.WireProtocol.Disconnect import io.iohk.ethereum.network.p2p.messages.WireProtocol.Disconnect.Reasons +import io.iohk.ethereum.network.p2p.{Message, MessageSerializable} import io.iohk.ethereum.utils.Logger -case class EtcNodeStatusExchangeState(handshakerConfiguration: EtcHandshakerConfiguration) - extends InProgressState[PeerInfo] - with Logger { +trait EtcNodeStatusExchangeState[T <: Message] extends InProgressState[PeerInfo] with Logger { + + val handshakerConfiguration: EtcHandshakerConfiguration import handshakerConfiguration._ @@ -21,49 +19,33 @@ case class EtcNodeStatusExchangeState(handshakerConfiguration: EtcHandshakerConf timeout = peerConfiguration.waitForStatusTimeout ) - def applyResponseMessage: PartialFunction[Message, HandshakerState[PeerInfo]] = { case remoteStatus: Status => - log.debug("Peer returned status ({})", remoteStatus) + def processTimeout: HandshakerState[PeerInfo] = { + log.debug("Timeout while waiting status") + DisconnectedState(Disconnect.Reasons.TimeoutOnReceivingAMessage) + } + + protected def applyRemoteStatusMessage: RemoteStatus => HandshakerState[PeerInfo] = { status: RemoteStatus => + log.debug("Peer returned status ({})", status) - val validNetworkID = remoteStatus.networkId == handshakerConfiguration.peerConfiguration.networkId - val validGenesisHash = remoteStatus.genesisHash == blockchain.genesisHeader.hash + val validNetworkID = status.networkId == handshakerConfiguration.peerConfiguration.networkId + val validGenesisHash = status.genesisHash == blockchain.genesisHeader.hash if (validNetworkID && validGenesisHash) { forkResolverOpt match { case Some(forkResolver) => - EtcForkBlockExchangeState(handshakerConfiguration, forkResolver, remoteStatus) + EtcForkBlockExchangeState(handshakerConfiguration, forkResolver, status) case None => - ConnectedState(PeerInfo.withForkAccepted(remoteStatus)) + ConnectedState(PeerInfo.withForkAccepted(status)) } } else DisconnectedState(Reasons.DisconnectRequested) - - } - - def processTimeout: HandshakerState[PeerInfo] = { - log.debug("Timeout while waiting status") - DisconnectedState(Disconnect.Reasons.TimeoutOnReceivingAMessage) } - private def getBestBlockHeader() = { + protected def getBestBlockHeader() = { val bestBlockNumber = blockchain.getBestBlockNumber() blockchain.getBlockHeaderByNumber(bestBlockNumber).getOrElse(blockchain.genesisHeader) } - private def createStatusMsg(): Status = { - val bestBlockHeader = getBestBlockHeader() - val chainWeight = blockchain.getChainWeightByHash(bestBlockHeader.hash).get - - val status = Status( - protocolVersion = Versions.PV63, - networkId = peerConfiguration.networkId, - chainWeight = chainWeight, - bestHash = bestBlockHeader.hash, - genesisHash = blockchain.genesisHeader.hash - ) - - val adjustedStatus = if (bestBlockHeader.number < blockchainConfig.ecip1097BlockNumber) status.as63 else status.as64 - log.debug(s"sending status $adjustedStatus") - adjustedStatus - } + protected def createStatusMsg(): MessageSerializable } diff --git a/src/main/scala/io/iohk/ethereum/network/p2p/MessageDecoders.scala b/src/main/scala/io/iohk/ethereum/network/p2p/MessageDecoders.scala index 3616c7fa66..983d0da0c3 100644 --- a/src/main/scala/io/iohk/ethereum/network/p2p/MessageDecoders.scala +++ b/src/main/scala/io/iohk/ethereum/network/p2p/MessageDecoders.scala @@ -1,35 +1,33 @@ package io.iohk.ethereum.network.p2p import io.iohk.ethereum.network.p2p.Message.Version -import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock._ +import io.iohk.ethereum.network.p2p.messages.Codes import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions._ -import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status._ -import io.iohk.ethereum.network.p2p.messages.CommonMessages._ import io.iohk.ethereum.network.p2p.messages.PV61.BlockHashesFromNumber._ -import io.iohk.ethereum.network.p2p.messages.PV62.NewBlockHashes._ import io.iohk.ethereum.network.p2p.messages.PV62.BlockBodies._ import io.iohk.ethereum.network.p2p.messages.PV62.BlockHeaders._ import io.iohk.ethereum.network.p2p.messages.PV62.GetBlockBodies._ import io.iohk.ethereum.network.p2p.messages.PV62.GetBlockHeaders._ +import io.iohk.ethereum.network.p2p.messages.PV62.NewBlockHashes._ import io.iohk.ethereum.network.p2p.messages.PV63.GetNodeData._ import io.iohk.ethereum.network.p2p.messages.PV63.GetReceipts._ import io.iohk.ethereum.network.p2p.messages.PV63.NodeData._ import io.iohk.ethereum.network.p2p.messages.PV63.Receipts._ +import io.iohk.ethereum.network.p2p.messages.ProtocolVersions._ import io.iohk.ethereum.network.p2p.messages.WireProtocol.Disconnect._ import io.iohk.ethereum.network.p2p.messages.WireProtocol.Hello._ import io.iohk.ethereum.network.p2p.messages.WireProtocol.Ping._ import io.iohk.ethereum.network.p2p.messages.WireProtocol.Pong._ import io.iohk.ethereum.network.p2p.messages.WireProtocol._ -import io.iohk.ethereum.network.p2p.messages.{PV61 => pv61, PV62 => pv62, PV63 => pv63} -import io.iohk.ethereum.network.p2p.messages.Versions._ object NetworkMessageDecoder extends MessageDecoder { override def fromBytes(msgCode: Int, payload: Array[Byte], protocolVersion: Version): Message = - (protocolVersion, msgCode) match { - case (_, Disconnect.code) => payload.toDisconnect - case (_, Ping.code) => payload.toPing - case (_, Pong.code) => payload.toPong + msgCode match { + case Disconnect.code => payload.toDisconnect + case Ping.code => payload.toPing + case Pong.code => payload.toPong + case Hello.code => payload.toHello case _ => throw new RuntimeException(s"Unknown message type: ${msgCode}") } @@ -38,45 +36,72 @@ object NetworkMessageDecoder extends MessageDecoder { // scalastyle:off object EthereumMessageDecoder extends MessageDecoder { - override def fromBytes(msgCode: Int, payload: Array[Byte], protocolVersion: Version): Message = - (protocolVersion, msgCode) match { - //wire protocol - case (_, Hello.code) => payload.toHello - - //FIXME: I still have an issue with protocolVersion, we are use PV62 and PV63 and code names for Status and NewBlock - // suggest that there is PV64, but there isn't - //common - case (_, Status.code63 | Status.code64) => payload.toStatus(msgCode) - case (_, SignedTransactions.code) => payload.toSignedTransactions - case (_, NewBlock.code63 | NewBlock.code64) => payload.toNewBlock(msgCode) - - case (PV61, t) => handlePV61(t, payload) + override def fromBytes(msgCode: Int, payload: Array[Byte], protocolVersion: Version): Message = { + protocolVersion match { + case PV61 => handlePV61(msgCode, payload) + case PV62 => handlePV62(msgCode, payload) + case PV63 => handlePV63(msgCode, payload) + case PV64 => handlePV64(msgCode, payload) + case pv => throw new RuntimeException("Unknown protocol version: " + pv) + } + } - case (PV62 | PV63, pv62.NewBlockHashes.code) => payload.toNewBlockHashes - case (PV62 | PV63, pv62.GetBlockHeaders.code) => payload.toGetBlockHeaders - case (PV62 | PV63, pv62.BlockHeaders.code) => payload.toBlockHeaders - case (PV62 | PV63, pv62.GetBlockBodies.code) => payload.toGetBlockBodies - case (PV62 | PV63, pv62.BlockBodies.code) => payload.toBlockBodies + private def handleCommonMessages(msgCode: Int, payload: Array[Byte]): Message = { + msgCode match { + case Codes.StatusCode => + import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status._ + payload.toStatus + case Codes.NewBlockCode => + import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock._ + payload.toNewBlock + case Codes.SignedTransactionsCode => + payload.toSignedTransactions + case _ => + throw new RuntimeException("Unknown message type: " + msgCode) + } + } - case (PV63, t) => handlePV63(t, payload) + private def handlePV61(msgCode: Int, payload: Array[Byte]): Message = { + msgCode match { + case Codes.NewBlockHashesCode => + import io.iohk.ethereum.network.p2p.messages.PV61.NewBlockHashes._ + payload.toNewBlockHashes + case Codes.BlockHashesFromNumberCode => + payload.toBlockHashesFromNumber + case _ => handleCommonMessages(msgCode, payload) + } + } - case _ => throw new RuntimeException(s"Unknown message type: ${msgCode}") + private def handlePV62(msgCode: Int, payload: Array[Byte]): Message = { + msgCode match { + case Codes.NewBlockHashesCode => payload.toNewBlockHashes + case Codes.GetBlockHeadersCode => payload.toGetBlockHeaders + case Codes.BlockHeadersCode => payload.toBlockHeaders + case Codes.GetBlockBodiesCode => payload.toGetBlockBodies + case Codes.BlockBodiesCode => payload.toBlockBodies + case _ => handleCommonMessages(msgCode, payload) } + } - private def handlePV61(msgCode: Int, payload: Array[Byte]): Message = { - import io.iohk.ethereum.network.p2p.messages.PV61.NewBlockHashes._ + private def handlePV63(msgCode: Int, payload: Array[Byte]): Message = { msgCode match { - case pv61.NewBlockHashes.code => payload.toNewBlockHashes - case pv61.BlockHashesFromNumber.code => payload.toBlockHashesFromNumber - case _ => throw new RuntimeException(s"Unknown message type: ${msgCode}") + case Codes.GetNodeDataCode => payload.toGetNodeData + case Codes.NodeDataCode => payload.toNodeData + case Codes.GetReceiptsCode => payload.toGetReceipts + case Codes.ReceiptsCode => payload.toReceipts + case _ => handlePV62(msgCode, payload) } } - private def handlePV63(msgCode: Int, payload: Array[Byte]): Message = msgCode match { - case pv63.GetNodeData.code => payload.toGetNodeData - case pv63.NodeData.code => payload.toNodeData - case pv63.GetReceipts.code => payload.toGetReceipts - case pv63.Receipts.code => payload.toReceipts - case _ => throw new RuntimeException(s"Unknown message type: ${msgCode}") + private def handlePV64(msgCode: Int, payload: Array[Byte]): Message = { + msgCode match { + case Codes.StatusCode => + import io.iohk.ethereum.network.p2p.messages.PV64.Status._ + payload.toStatus + case Codes.NewBlockCode => + import io.iohk.ethereum.network.p2p.messages.PV64.NewBlock._ + payload.toNewBlock + case _ => handlePV63(msgCode, payload) + } } } diff --git a/src/main/scala/io/iohk/ethereum/network/p2p/messages/Capability.scala b/src/main/scala/io/iohk/ethereum/network/p2p/messages/Capability.scala new file mode 100644 index 0000000000..6618e69c8b --- /dev/null +++ b/src/main/scala/io/iohk/ethereum/network/p2p/messages/Capability.scala @@ -0,0 +1,31 @@ +package io.iohk.ethereum.network.p2p.messages + +import io.iohk.ethereum.rlp.RLPImplicitConversions._ +import io.iohk.ethereum.rlp.RLPImplicits._ +import io.iohk.ethereum.rlp.{RLPEncodeable, RLPException, RLPList, RLPSerializable, rawDecode} + +case class Capability(name: String, version: Byte) + +object Capability { + implicit class CapabilityEnc(val msg: Capability) extends RLPSerializable { + override def toRLPEncodable: RLPEncodeable = RLPList(msg.name, msg.version) + } + + implicit class CapabilityDec(val bytes: Array[Byte]) extends AnyVal { + def toCapability: Capability = CapabilityRLPEncodableDec(rawDecode(bytes)).toCapability + } + + implicit class CapabilityRLPEncodableDec(val rLPEncodeable: RLPEncodeable) extends AnyVal { + def toCapability: Capability = rLPEncodeable match { + case RLPList(name, version) => Capability(name, version) + case _ => throw new RLPException("Cannot decode Capability") + } + } + + object Capabilities { + val Eth63Capability: Capability = Capability("eth", ProtocolVersions.PV63.toByte) + val Etc64Capability: Capability = Capability("etc", ProtocolVersions.PV64.toByte) + + val All: Seq[Capability] = Seq(Etc64Capability, Eth63Capability) + } +} diff --git a/src/main/scala/io/iohk/ethereum/network/p2p/messages/CommonMessages.scala b/src/main/scala/io/iohk/ethereum/network/p2p/messages/CommonMessages.scala index 2f16312b47..c8e1f7cc54 100644 --- a/src/main/scala/io/iohk/ethereum/network/p2p/messages/CommonMessages.scala +++ b/src/main/scala/io/iohk/ethereum/network/p2p/messages/CommonMessages.scala @@ -1,8 +1,8 @@ package io.iohk.ethereum.network.p2p.messages import akka.util.ByteString -import io.iohk.ethereum.domain._ import io.iohk.ethereum.domain.BlockHeaderImplicits._ +import io.iohk.ethereum.domain._ import io.iohk.ethereum.network.p2p.{Message, MessageSerializableImplicit} import io.iohk.ethereum.rlp.RLPImplicitConversions._ import io.iohk.ethereum.rlp.RLPImplicits._ @@ -12,70 +12,30 @@ import org.bouncycastle.util.encoders.Hex object CommonMessages { object Status { - val code63: Int = Versions.SubProtocolOffset + 0x00 - val code64: Int = Versions.SubProtocolOffset + 0x11 - implicit class StatusEnc(val underlyingMsg: Status) extends MessageSerializableImplicit[Status](underlyingMsg) with RLPSerializable { - override def code: Int = underlyingMsg.code + override def code: Int = Codes.StatusCode override def toRLPEncodable: RLPEncodeable = { import msg._ - msg.code match { - case `code63` => - RLPList(protocolVersion, networkId, chainWeight.totalDifficulty, bestHash, genesisHash) + RLPList(protocolVersion, networkId, totalDifficulty, bestHash, genesisHash) + } + } - case `code64` => - RLPList( + implicit class StatusDec(val bytes: Array[Byte]) extends AnyVal { + def toStatus: Status = rawDecode(bytes) match { + case RLPList( protocolVersion, networkId, - chainWeight.totalDifficulty, - chainWeight.lastCheckpointNumber, + totalDifficulty, bestHash, genesisHash - ) - } - } - } - - implicit class StatusDec(val bytes: Array[Byte]) extends AnyVal { - def toStatus(code: Int): Status = (code, rawDecode(bytes)) match { - case ( - `code63`, - RLPList( - protocolVersion, - networkId, - totalDifficulty, - bestHash, - genesisHash - ) ) => Status( - code63, protocolVersion, networkId, - ChainWeight.totalDifficultyOnly(totalDifficulty), - bestHash, - genesisHash - ) - - case ( - `code64`, - RLPList( - protocolVersion, - networkId, - totalDifficulty, - lastCheckpointNumber, - bestHash, - genesisHash - ) - ) => - Status( - code64, - protocolVersion, - networkId, - ChainWeight(lastCheckpointNumber, totalDifficulty), + totalDifficulty, bestHash, genesisHash ) @@ -84,56 +44,90 @@ object CommonMessages { } } - /** - * Constructs the message with it specifying the code. The code should be regarded as undefined at this stage. - * It should be later made concrete with `as63` or `as64` methods. - * - * FIXME this approach was taken to minimise the required refactoring and should be reconsidered in ETCM-280 - */ - def apply( - protocolVersion: Int, - networkId: Int, - chainWeight: ChainWeight, - bestHash: ByteString, - genesisHash: ByteString - ): Status = - Status(Status.code63, protocolVersion, networkId, chainWeight, bestHash, genesisHash) - } + /** + * used by eth61, eth62, eth63 + */ case class Status( - code: Int, protocolVersion: Int, networkId: Int, - chainWeight: ChainWeight, + totalDifficulty: BigInt, bestHash: ByteString, genesisHash: ByteString ) extends Message { - require(code == Status.code63 || code == Status.code64, s"Invalid code for Status: $code") override def toString: String = s"Status { " + s"code: $code, " + s"protocolVersion: $protocolVersion, " + s"networkId: $networkId, " + - s"chainWeight: $chainWeight, " + + s"totalDifficulty: $totalDifficulty, " + s"bestHash: ${Hex.toHexString(bestHash.toArray[Byte])}, " + s"genesisHash: ${Hex.toHexString(genesisHash.toArray[Byte])}," + s"}" - def as63: Status = - copy(code = Status.code63) + override def code: Int = Codes.StatusCode + } + + object NewBlock { + implicit class NewBlockEnc(val underlyingMsg: NewBlock) + extends MessageSerializableImplicit[NewBlock](underlyingMsg) + with RLPSerializable { + import SignedTransactions._ + + override def code: Int = Codes.NewBlockCode + + override def toRLPEncodable: RLPEncodeable = { + import msg._ + RLPList( + RLPList( + block.header.toRLPEncodable, + RLPList(block.body.transactionList.map(_.toRLPEncodable): _*), + RLPList(block.body.uncleNodesList.map(_.toRLPEncodable): _*) + ), + totalDifficulty + ) + } + } + + implicit class NewBlockDec(val bytes: Array[Byte]) extends AnyVal { + import SignedTransactions._ + + def toNewBlock: NewBlock = rawDecode(bytes) match { + case RLPList(RLPList(blockHeader, transactionList: RLPList, uncleNodesList: RLPList), totalDifficulty) => + NewBlock( + Block( + blockHeader.toBlockHeader, + BlockBody(transactionList.items.map(_.toSignedTransaction), uncleNodesList.items.map(_.toBlockHeader)) + ), + totalDifficulty + ) + + case _ => throw new RuntimeException("Cannot decode NewBlock") + } + } + } + + /** + * used by eth61, eth62, eth63 + */ + case class NewBlock(block: Block, totalDifficulty: BigInt) extends Message { + + override def toString: String = + s"NewBlock { " + + s"code: $code, " + + s"block: $block, " + + s"totalDifficulty: $totalDifficulty" + + s"}" - def as64: Status = - copy(code = Status.code64) + override def code: Int = Codes.NewBlockCode } object SignedTransactions { lazy val chainId: Byte = Config.blockchains.blockchainConfig.chainId - val code: Int = Versions.SubProtocolOffset + 0x02 - implicit class SignedTransactionEnc(val signedTx: SignedTransaction) extends RLPSerializable { override def toRLPEncodable: RLPEncodeable = { val receivingAddressBytes = signedTx.tx.receivingAddress @@ -157,7 +151,7 @@ object CommonMessages { extends MessageSerializableImplicit[SignedTransactions](underlyingMsg) with RLPSerializable { - override def code: Int = SignedTransactions.code + override def code: Int = Codes.SignedTransactionsCode override def toRLPEncodable: RLPEncodeable = RLPList(msg.txs.map(_.toRLPEncodable): _*) } @@ -198,111 +192,6 @@ object CommonMessages { } case class SignedTransactions(txs: Seq[SignedTransaction]) extends Message { - override def code: Int = SignedTransactions.code - } - - object NewBlock { - - val code63: Int = Versions.SubProtocolOffset + 0x07 - val code64: Int = Versions.SubProtocolOffset + 0x12 - - implicit class NewBlockEnc(val underlyingMsg: NewBlock) - extends MessageSerializableImplicit[NewBlock](underlyingMsg) - with RLPSerializable { - import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions._ - - override def code: Int = msg.code - - override def toRLPEncodable: RLPEncodeable = { - import msg._ - msg.code match { - case `code63` => - RLPList( - RLPList( - block.header.toRLPEncodable, - RLPList(block.body.transactionList.map(_.toRLPEncodable): _*), - RLPList(block.body.uncleNodesList.map(_.toRLPEncodable): _*) - ), - chainWeight.totalDifficulty - ) - - case `code64` => - RLPList( - RLPList( - block.header.toRLPEncodable, - RLPList(block.body.transactionList.map(_.toRLPEncodable): _*), - RLPList(block.body.uncleNodesList.map(_.toRLPEncodable): _*) - ), - chainWeight.totalDifficulty, - chainWeight.lastCheckpointNumber - ) - } - - } - } - - implicit class NewBlockDec(val bytes: Array[Byte]) extends AnyVal { - import SignedTransactions._ - - def toNewBlock(code: Int): NewBlock = (code, rawDecode(bytes)) match { - case ( - `code63`, - RLPList(RLPList(blockHeader, (transactionList: RLPList), (uncleNodesList: RLPList)), totalDifficulty) - ) => - NewBlock( - code63, - Block( - blockHeader.toBlockHeader, - BlockBody(transactionList.items.map(_.toSignedTransaction), uncleNodesList.items.map(_.toBlockHeader)) - ), - ChainWeight.totalDifficultyOnly(totalDifficulty) - ) - - case ( - `code64`, - RLPList( - RLPList(blockHeader, (transactionList: RLPList), (uncleNodesList: RLPList)), - totalDifficulty, - lastCheckpointNumber - ) - ) => - NewBlock( - code64, - Block( - blockHeader.toBlockHeader, - BlockBody(transactionList.items.map(_.toSignedTransaction), uncleNodesList.items.map(_.toBlockHeader)) - ), - ChainWeight(lastCheckpointNumber, totalDifficulty) - ) - case _ => throw new RuntimeException("Cannot decode NewBlock") - } - } - - /** - * Constructs the message with it specifying the code. The code should be regarded as undefined at this stage. - * It should be later made concrete with `as63` or `as64` methods. - * - * FIXME this approach was taken to minimise the required refactoring and should be reconsidered in ETCM-280 - */ - def apply(block: Block, chainWeight: ChainWeight): NewBlock = - NewBlock(NewBlock.code63, block, chainWeight) - - } - - case class NewBlock(code: Int, block: Block, chainWeight: ChainWeight) extends Message { - require(code == NewBlock.code63 || code == NewBlock.code64, s"Invalid code for NewBlock: $code") - - override def toString: String = - s"NewBlock { " + - s"code: $code, " + - s"block: $block, " + - s"chainWeight: $chainWeight" + - s"}" - - def as63: NewBlock = - copy(code = NewBlock.code63) - - def as64: NewBlock = - copy(code = NewBlock.code64) + override def code: Int = Codes.SignedTransactionsCode } } diff --git a/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV61.scala b/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV61.scala index 52c7c288b6..3483624748 100644 --- a/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV61.scala +++ b/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV61.scala @@ -9,13 +9,11 @@ import io.iohk.ethereum.rlp._ object PV61 { object NewBlockHashes { - val code: Int = Versions.SubProtocolOffset + 0x01 - implicit class NewBlockHashesEnc(val underlyingMsg: NewBlockHashes) extends MessageSerializableImplicit[NewBlockHashes](underlyingMsg) with RLPSerializable { - override def code: Int = NewBlockHashes.code + override def code: Int = Codes.NewBlockHashesCode override def toRLPEncodable: RLPEncodeable = RLPList(msg.hashes.map(e => RLPValue(e.toArray[Byte])): _*) } @@ -30,18 +28,15 @@ object PV61 { } case class NewBlockHashes(hashes: Seq[ByteString]) extends Message { - override def code: Int = NewBlockHashes.code + override def code: Int = Codes.NewBlockHashesCode } object BlockHashesFromNumber { - - val code: Int = Versions.SubProtocolOffset + 0x08 - implicit class BlockHashesFromNumberEnc(val underlyingMsg: BlockHashesFromNumber) extends MessageSerializableImplicit[BlockHashesFromNumber](underlyingMsg) with RLPSerializable { - override def code: Int = BlockHashesFromNumber.code + override def code: Int = Codes.BlockHashesFromNumberCode override def toRLPEncodable: RLPEncodeable = RLPList(msg.number, msg.maxBlocks) } @@ -55,7 +50,7 @@ object PV61 { } case class BlockHashesFromNumber(number: BigInt, maxBlocks: BigInt) extends Message { - override def code: Int = BlockHashesFromNumber.code + override def code: Int = Codes.BlockHashesFromNumberCode } } diff --git a/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV62.scala b/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV62.scala index 3814eceb00..fc240e24b2 100644 --- a/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV62.scala +++ b/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV62.scala @@ -38,16 +38,13 @@ object PV62 { } object NewBlockHashes { - - val code: Int = Versions.SubProtocolOffset + 0x01 - implicit class NewBlockHashesEnc(val underlyingMsg: NewBlockHashes) extends MessageSerializableImplicit[NewBlockHashes](underlyingMsg) with RLPSerializable { import BlockHash._ - override def code: Int = NewBlockHashes.code + override def code: Int = Codes.NewBlockHashesCode override def toRLPEncodable: RLPEncodeable = RLPList(msg.hashes.map(_.toRLPEncodable): _*) } @@ -62,17 +59,15 @@ object PV62 { } case class NewBlockHashes(hashes: Seq[BlockHash]) extends Message { - override def code: Int = NewBlockHashes.code + override def code: Int = Codes.NewBlockHashesCode } object GetBlockHeaders { - val code: Int = Versions.SubProtocolOffset + 0x03 - implicit class GetBlockHeadersEnc(val underlyingMsg: GetBlockHeaders) extends MessageSerializableImplicit[GetBlockHeaders](underlyingMsg) with RLPSerializable { - override def code: Int = GetBlockHeaders.code + override def code: Int = Codes.GetBlockHeadersCode override def toRLPEncodable: RLPEncodeable = { import msg._ @@ -98,7 +93,7 @@ object PV62 { case class GetBlockHeaders(block: Either[BigInt, ByteString], maxHeaders: BigInt, skip: BigInt, reverse: Boolean) extends Message { - override def code: Int = GetBlockHeaders.code + override def code: Int = Codes.GetBlockHeadersCode override def toString: String = s"GetBlockHeaders{ " + @@ -110,13 +105,10 @@ object PV62 { } object BlockBodies { - - val code: Int = Versions.SubProtocolOffset + 0x06 - implicit class BlockBodiesEnc(val underlyingMsg: BlockBodies) extends MessageSerializableImplicit[BlockBodies](underlyingMsg) with RLPSerializable { - override def code: Int = BlockBodies.code + override def code: Int = Codes.BlockBodiesCode override def toRLPEncodable: RLPEncodeable = RLPList(msg.bodies.map(_.toRLPEncodable): _*) } @@ -130,18 +122,15 @@ object PV62 { } case class BlockBodies(bodies: Seq[BlockBody]) extends Message { - val code: Int = BlockBodies.code + val code: Int = Codes.BlockBodiesCode } object BlockHeaders { - - val code: Int = Versions.SubProtocolOffset + 0x04 - implicit class BlockHeadersEnc(val underlyingMsg: BlockHeaders) extends MessageSerializableImplicit[BlockHeaders](underlyingMsg) with RLPSerializable { - override def code: Int = BlockHeaders.code + override def code: Int = Codes.BlockHeadersCode override def toRLPEncodable: RLPEncodeable = RLPList(msg.headers.map(_.toRLPEncodable): _*) } @@ -158,18 +147,15 @@ object PV62 { } case class BlockHeaders(headers: Seq[BlockHeader]) extends Message { - override def code: Int = BlockHeaders.code + override def code: Int = Codes.BlockHeadersCode } object GetBlockBodies { - - val code: Int = Versions.SubProtocolOffset + 0x05 - implicit class GetBlockBodiesEnc(val underlyingMsg: GetBlockBodies) extends MessageSerializableImplicit[GetBlockBodies](underlyingMsg) with RLPSerializable { - override def code: Int = GetBlockBodies.code + override def code: Int = Codes.GetBlockBodiesCode override def toRLPEncodable: RLPEncodeable = toRlpList(msg.hashes) } @@ -184,7 +170,7 @@ object PV62 { } case class GetBlockBodies(hashes: Seq[ByteString]) extends Message { - override def code: Int = GetBlockBodies.code + override def code: Int = Codes.GetBlockBodiesCode override def toString: String = s"GetBlockBodies { " + diff --git a/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV63.scala b/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV63.scala index bd16720ff7..465342219d 100644 --- a/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV63.scala +++ b/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV63.scala @@ -12,13 +12,10 @@ import org.bouncycastle.util.encoders.Hex object PV63 { object GetNodeData { - - val code: Int = Versions.SubProtocolOffset + 0x0d - implicit class GetNodeDataEnc(val underlyingMsg: GetNodeData) extends MessageSerializableImplicit[GetNodeData](underlyingMsg) with RLPSerializable { - override def code: Int = GetNodeData.code + override def code: Int = Codes.GetNodeDataCode override def toRLPEncodable: RLPEncodeable = toRlpList(msg.mptElementsHashes) } @@ -32,7 +29,7 @@ object PV63 { } case class GetNodeData(mptElementsHashes: Seq[ByteString]) extends Message { - override def code: Int = GetNodeData.code + override def code: Int = Codes.GetNodeDataCode override def toString: String = s"GetNodeData{ hashes: ${mptElementsHashes.map(e => Hex.toHexString(e.toArray[Byte]))} }" @@ -79,16 +76,13 @@ object PV63 { } object NodeData { - - val code: Int = Versions.SubProtocolOffset + 0x0e - implicit class NodeDataEnc(val underlyingMsg: NodeData) extends MessageSerializableImplicit[NodeData](underlyingMsg) with RLPSerializable { import MptNodeEncoders._ - override def code: Int = NodeData.code + override def code: Int = Codes.NodeDataCode override def toRLPEncodable: RLPEncodeable = msg.values @throws[RLPException] @@ -105,19 +99,17 @@ object PV63 { case class NodeData(values: Seq[ByteString]) extends Message { - override def code: Int = NodeData.code + override def code: Int = Codes.NodeDataCode override def toString: String = s"NodeData{ values: ${values.map(b => Hex.toHexString(b.toArray[Byte]))} }" } object GetReceipts { - val code: Int = Versions.SubProtocolOffset + 0x0f - implicit class GetReceiptsEnc(val underlyingMsg: GetReceipts) extends MessageSerializableImplicit[GetReceipts](underlyingMsg) with RLPSerializable { - override def code: Int = GetReceipts.code + override def code: Int = Codes.GetReceiptsCode override def toRLPEncodable: RLPEncodeable = msg.blockHashes: RLPList } @@ -131,7 +123,7 @@ object PV63 { } case class GetReceipts(blockHashes: Seq[ByteString]) extends Message { - override def code: Int = GetReceipts.code + override def code: Int = Codes.GetReceiptsCode override def toString: String = { s"GetReceipts{ blockHashes: ${blockHashes.map(e => Hex.toHexString(e.toArray[Byte]))} } " @@ -200,15 +192,12 @@ object PV63 { } object Receipts { - - val code: Int = Versions.SubProtocolOffset + 0x10 - implicit class ReceiptsEnc(val underlyingMsg: Receipts) extends MessageSerializableImplicit[Receipts](underlyingMsg) with RLPSerializable { import ReceiptImplicits._ - override def code: Int = Receipts.code + override def code: Int = Codes.ReceiptsCode override def toRLPEncodable: RLPEncodeable = RLPList( msg.receiptsForBlocks.map((rs: Seq[Receipt]) => RLPList(rs.map((r: Receipt) => r.toRLPEncodable): _*)): _* @@ -226,6 +215,6 @@ object PV63 { } case class Receipts(receiptsForBlocks: Seq[Seq[Receipt]]) extends Message { - override def code: Int = Receipts.code + override def code: Int = Codes.ReceiptsCode } } diff --git a/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV64.scala b/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV64.scala new file mode 100644 index 0000000000..3e69e453f5 --- /dev/null +++ b/src/main/scala/io/iohk/ethereum/network/p2p/messages/PV64.scala @@ -0,0 +1,132 @@ +package io.iohk.ethereum.network.p2p.messages + +import akka.util.ByteString +import io.iohk.ethereum.domain.BlockHeaderImplicits._ +import io.iohk.ethereum.domain._ +import io.iohk.ethereum.network.p2p.{Message, MessageSerializableImplicit} +import io.iohk.ethereum.rlp.RLPImplicitConversions._ +import io.iohk.ethereum.rlp.RLPImplicits._ +import io.iohk.ethereum.rlp._ +import org.bouncycastle.util.encoders.Hex + +/** + * This is temporal PV64 version, the real one will be implemented by ETCM-355 + * This one will be probably PV66 in the future + */ +object PV64 { + object Status { + implicit class StatusEnc(val underlyingMsg: Status) + extends MessageSerializableImplicit[Status](underlyingMsg) + with RLPSerializable { + override def code: Int = Codes.StatusCode + + override def toRLPEncodable: RLPEncodeable = { + import msg._ + RLPList( + protocolVersion, + networkId, + chainWeight.totalDifficulty, + chainWeight.lastCheckpointNumber, + bestHash, + genesisHash + ) + } + } + + implicit class StatusDec(val bytes: Array[Byte]) extends AnyVal { + def toStatus: Status = rawDecode(bytes) match { + case RLPList( + protocolVersion, + networkId, + totalDifficulty, + lastCheckpointNumber, + bestHash, + genesisHash + ) => + Status( + protocolVersion, + networkId, + ChainWeight(lastCheckpointNumber, totalDifficulty), + bestHash, + genesisHash + ) + + case _ => throw new RuntimeException("Cannot decode Status PV64 version") + } + } + + } + + case class Status( + protocolVersion: Int, + networkId: Int, + chainWeight: ChainWeight, + bestHash: ByteString, + genesisHash: ByteString + ) extends Message { + + override def toString: String = + s"Status { " + + s"protocolVersion: $protocolVersion, " + + s"networkId: $networkId, " + + s"chainWeight: $chainWeight, " + + s"bestHash: ${Hex.toHexString(bestHash.toArray[Byte])}, " + + s"genesisHash: ${Hex.toHexString(genesisHash.toArray[Byte])}," + + s"}" + + override def code: Int = Codes.StatusCode + } + + object NewBlock { + implicit class NewBlockEnc(val underlyingMsg: NewBlock) + extends MessageSerializableImplicit[NewBlock](underlyingMsg) + with RLPSerializable { + import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions._ + + override def code: Int = Codes.NewBlockCode + + override def toRLPEncodable: RLPEncodeable = { + import msg._ + RLPList( + RLPList( + block.header.toRLPEncodable, + RLPList(block.body.transactionList.map(_.toRLPEncodable): _*), + RLPList(block.body.uncleNodesList.map(_.toRLPEncodable): _*) + ), + chainWeight.totalDifficulty, + chainWeight.lastCheckpointNumber + ) + } + } + + implicit class NewBlockDec(val bytes: Array[Byte]) extends AnyVal { + import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions._ + + def toNewBlock: NewBlock = rawDecode(bytes) match { + case RLPList( + RLPList(blockHeader, transactionList: RLPList, (uncleNodesList: RLPList)), + totalDifficulty, + lastCheckpointNumber + ) => + NewBlock( + Block( + blockHeader.toBlockHeader, + BlockBody(transactionList.items.map(_.toSignedTransaction), uncleNodesList.items.map(_.toBlockHeader)) + ), + ChainWeight(lastCheckpointNumber, totalDifficulty) + ) + case _ => throw new RuntimeException("Cannot decode NewBlock PV64 version") + } + } + } + + case class NewBlock(block: Block, chainWeight: ChainWeight) extends Message { + override def toString: String = + s"NewBlock { " + + s"block: $block, " + + s"chainWeight: $chainWeight" + + s"}" + + override def code: Int = Codes.NewBlockCode + } +} diff --git a/src/main/scala/io/iohk/ethereum/network/p2p/messages/WireProtocol.scala b/src/main/scala/io/iohk/ethereum/network/p2p/messages/WireProtocol.scala index 7a45e5482b..3103f6c031 100644 --- a/src/main/scala/io/iohk/ethereum/network/p2p/messages/WireProtocol.scala +++ b/src/main/scala/io/iohk/ethereum/network/p2p/messages/WireProtocol.scala @@ -9,25 +9,6 @@ import org.bouncycastle.util.encoders.Hex object WireProtocol { - object Capability { - implicit class CapabilityEnc(val msg: Capability) extends RLPSerializable { - override def toRLPEncodable: RLPEncodeable = RLPList(msg.name, msg.version) - } - - implicit class CapabilityDec(val bytes: Array[Byte]) extends AnyVal { - def toCapability: Capability = CapabilityRLPEncodableDec(rawDecode(bytes)).toCapability - } - - implicit class CapabilityRLPEncodableDec(val rLPEncodeable: RLPEncodeable) extends AnyVal { - def toCapability: Capability = rLPEncodeable match { - case RLPList(name, version) => Capability(name, version) - case _ => throw new RuntimeException("Cannot decode Capability") - } - } - } - - case class Capability(name: String, version: Byte) - object Hello { val code = 0x00 diff --git a/src/main/scala/io/iohk/ethereum/network/p2p/messages/package.scala b/src/main/scala/io/iohk/ethereum/network/p2p/messages/package.scala index 258c8e54e5..589ddff766 100644 --- a/src/main/scala/io/iohk/ethereum/network/p2p/messages/package.scala +++ b/src/main/scala/io/iohk/ethereum/network/p2p/messages/package.scala @@ -3,11 +3,29 @@ package io.iohk.ethereum.network.p2p import io.iohk.ethereum.network.p2p.Message.Version package object messages { - object Versions { + object ProtocolVersions { val PV61: Version = 61 val PV62: Version = 62 val PV63: Version = 63 + val PV64: Version = 64 val SubProtocolOffset = 0x10 } + + object Codes { + val StatusCode: Int = ProtocolVersions.SubProtocolOffset + 0x00 + val NewBlockHashesCode: Int = ProtocolVersions.SubProtocolOffset + 0x01 + val SignedTransactionsCode: Int = ProtocolVersions.SubProtocolOffset + 0x02 + val GetBlockHeadersCode: Int = ProtocolVersions.SubProtocolOffset + 0x03 + val BlockHeadersCode: Int = ProtocolVersions.SubProtocolOffset + 0x04 + val GetBlockBodiesCode: Int = ProtocolVersions.SubProtocolOffset + 0x05 + val BlockBodiesCode: Int = ProtocolVersions.SubProtocolOffset + 0x06 + val NewBlockCode: Int = ProtocolVersions.SubProtocolOffset + 0x07 + // This message is removed in PV62 and this code is reused in PV65 with different msg type + val BlockHashesFromNumberCode: Int = ProtocolVersions.SubProtocolOffset + 0x08 + val GetNodeDataCode: Int = ProtocolVersions.SubProtocolOffset + 0x0d + val NodeDataCode: Int = ProtocolVersions.SubProtocolOffset + 0x0e + val GetReceiptsCode: Int = ProtocolVersions.SubProtocolOffset + 0x0f + val ReceiptsCode: Int = ProtocolVersions.SubProtocolOffset + 0x10 + } } diff --git a/src/main/scala/io/iohk/ethereum/network/rlpx/MessageCodec.scala b/src/main/scala/io/iohk/ethereum/network/rlpx/MessageCodec.scala index ac9e672acc..ec3e9dc91e 100644 --- a/src/main/scala/io/iohk/ethereum/network/rlpx/MessageCodec.scala +++ b/src/main/scala/io/iohk/ethereum/network/rlpx/MessageCodec.scala @@ -33,6 +33,7 @@ class MessageCodec(frameCodec: FrameCodec, messageDecoder: MessageDecoder, proto } } + // TODO: ETCM-402 - messageDecoder should use negotiated protocol version def readMessages(data: ByteString): Seq[Try[Message]] = { val frames = frameCodec.readFrames(data) diff --git a/src/main/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandler.scala b/src/main/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandler.scala index dc992879c9..f288604c3e 100644 --- a/src/main/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandler.scala +++ b/src/main/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandler.scala @@ -20,7 +20,7 @@ import scala.util.{Failure, Success, Try} * Once such connection is established it allows to send/receive frames (messages) over it. * * The actor can be in one of four states: - * 1. when created it waits for initial command (either handle incoming connection or connect usin g uri) + * 1. when created it waits for initial command (either handle incoming connection or connect using uri) * 2. when new connection is requested the actor waits for the result (waitingForConnectionResult) * 3. once underlying connection is established it either waits for handshake init message or for response message * (depending on who initiated the connection) diff --git a/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala b/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala index bda94ba34a..e2c6b1abce 100644 --- a/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala @@ -156,7 +156,6 @@ trait HandshakerBuilder { with NodeStatusBuilder with StorageBuilder with PeerManagerActorBuilder - with BlockchainConfigBuilder with ForkResolverBuilder => private val handshakerConfiguration: EtcHandshakerConfiguration = @@ -165,8 +164,8 @@ trait HandshakerBuilder { override val nodeStatusHolder: AtomicReference[NodeStatus] = self.nodeStatusHolder override val peerConfiguration: PeerConfiguration = self.peerConfiguration override val blockchain: Blockchain = self.blockchain - override val blockchainConfig: BlockchainConfig = self.blockchainConfig override val appStateStorage: AppStateStorage = self.storagesInstance.storages.appStateStorage + override val protocolVersion: Int = Config.Network.protocolVersion } lazy val handshaker: Handshaker[PeerInfo] = EtcHandshaker(handshakerConfiguration) @@ -206,7 +205,8 @@ trait PeerManagerActorBuilder { handshaker, authHandshaker, EthereumMessageDecoder, - discoveryConfig + discoveryConfig, + Config.Network.protocolVersion ), "peer-manager" ) @@ -551,7 +551,6 @@ trait SyncControllerBuilder { with BlockchainBuilder with NodeStatusBuilder with StorageBuilder - with BlockchainConfigBuilder with LedgerBuilder with PeerEventBusBuilder with PendingTransactionsManagerBuilder @@ -566,7 +565,6 @@ trait SyncControllerBuilder { SyncController.props( storagesInstance.storages.appStateStorage, blockchain, - blockchainConfig, storagesInstance.storages.fastSyncStateStorage, ledger, consensus.validators, diff --git a/src/main/scala/io/iohk/ethereum/transactions/SignedTransactionsFilterActor.scala b/src/main/scala/io/iohk/ethereum/transactions/SignedTransactionsFilterActor.scala index 01aafbb8e4..1dc03d7855 100644 --- a/src/main/scala/io/iohk/ethereum/transactions/SignedTransactionsFilterActor.scala +++ b/src/main/scala/io/iohk/ethereum/transactions/SignedTransactionsFilterActor.scala @@ -7,6 +7,7 @@ import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.MessageFromPeer import io.iohk.ethereum.network.PeerEventBusActor.{PeerSelector, Subscribe} import io.iohk.ethereum.network.PeerEventBusActor.SubscriptionClassifier.MessageClassifier import io.iohk.ethereum.network.PeerId +import io.iohk.ethereum.network.p2p.messages.Codes import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions import io.iohk.ethereum.transactions.SignedTransactionsFilterActor.ProperSignedTransactions @@ -14,7 +15,7 @@ class SignedTransactionsFilterActor(pendingTransactionsManager: ActorRef, peerEv extends Actor with RequiresMessageQueue[BoundedMessageQueueSemantics] { - peerEventBus ! Subscribe(MessageClassifier(Set(SignedTransactions.code), PeerSelector.AllPeers)) + peerEventBus ! Subscribe(MessageClassifier(Set(Codes.SignedTransactionsCode), PeerSelector.AllPeers)) override def receive: Receive = { case MessageFromPeer(SignedTransactions(newTransactions), peerId) => val correctTransactions = SignedTransactionWithSender.getSignedTransactions(newTransactions) diff --git a/src/test/scala/io/iohk/ethereum/Mocks.scala b/src/test/scala/io/iohk/ethereum/Mocks.scala index eec1a9d3cc..9ac1693f6d 100644 --- a/src/test/scala/io/iohk/ethereum/Mocks.scala +++ b/src/test/scala/io/iohk/ethereum/Mocks.scala @@ -12,9 +12,8 @@ import io.iohk.ethereum.consensus.{Consensus, GetBlockHeaderByHash, GetNBlocksBa import io.iohk.ethereum.domain._ import io.iohk.ethereum.ledger.BlockExecutionError.ValidationAfterExecError import io.iohk.ethereum.ledger._ -import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} import io.iohk.ethereum.network.handshaker.{ConnectedState, DisconnectedState, Handshaker, HandshakerState} -import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status import io.iohk.ethereum.vm._ import scala.concurrent.{ExecutionContext, Future} @@ -130,7 +129,7 @@ object Mocks { } } - case class MockHandshakerAlwaysSucceeds(initialStatus: Status, currentMaxBlockNumber: BigInt, forkAccepted: Boolean) + case class MockHandshakerAlwaysSucceeds(initialStatus: RemoteStatus, currentMaxBlockNumber: BigInt, forkAccepted: Boolean) extends Handshaker[PeerInfo] { override val handshakerState: HandshakerState[PeerInfo] = ConnectedState( diff --git a/src/test/scala/io/iohk/ethereum/ObjectGenerators.scala b/src/test/scala/io/iohk/ethereum/ObjectGenerators.scala index 9124cc6b2f..f02f3dc910 100644 --- a/src/test/scala/io/iohk/ethereum/ObjectGenerators.scala +++ b/src/test/scala/io/iohk/ethereum/ObjectGenerators.scala @@ -6,14 +6,15 @@ import java.security.SecureRandom import akka.util.ByteString import io.iohk.ethereum.blockchain.sync.StateSyncUtils.MptNodeData import io.iohk.ethereum.crypto.ECDSASignature +import io.iohk.ethereum.domain.BlockHeader.HeaderExtraFields +import io.iohk.ethereum.domain.BlockHeader.HeaderExtraFields._ +import io.iohk.ethereum.domain._ import io.iohk.ethereum.mpt.HexPrefix.bytesToNibbles -import org.scalacheck.{Arbitrary, Gen, Shrink} import io.iohk.ethereum.mpt.{BranchNode, ExtensionNode, HashNode, LeafNode, MptNode, MptTraversals} -import io.iohk.ethereum.domain._ import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock -import io.iohk.ethereum.domain.BlockHeader.HeaderExtraFields -import io.iohk.ethereum.domain.BlockHeader.HeaderExtraFields._ +import io.iohk.ethereum.network.p2p.messages.PV64 import org.bouncycastle.crypto.AsymmetricCipherKeyPair +import org.scalacheck.{Arbitrary, Gen, Shrink} // scalastyle:off number.of.methods trait ObjectGenerators { @@ -152,9 +153,16 @@ trait ObjectGenerators { blockHeader <- blockHeaderGen stxs <- signedTxSeqGen(10, secureRandom, chainId) uncles <- seqBlockHeaderGen - lastChkp <- bigIntGen td <- bigIntGen - } yield NewBlock(Block(blockHeader, BlockBody(stxs, uncles)), ChainWeight(lastChkp, td)) + } yield NewBlock(Block(blockHeader, BlockBody(stxs, uncles)), td) + + def newBlock64Gen(secureRandom: SecureRandom, chainId: Option[Byte]): Gen[PV64.NewBlock] = for { + blockHeader <- blockHeaderGen + stxs <- signedTxSeqGen(10, secureRandom, chainId) + uncles <- seqBlockHeaderGen + chainWeight <- chainWeightGen + } yield PV64.NewBlock(Block(blockHeader, BlockBody(stxs, uncles)), chainWeight) + def extraFieldsGen: Gen[HeaderExtraFields] = for { optOut <- Arbitrary.arbitrary[Option[Boolean]] diff --git a/src/test/scala/io/iohk/ethereum/blockchain/sync/BlockBroadcastSpec.scala b/src/test/scala/io/iohk/ethereum/blockchain/sync/BlockBroadcastSpec.scala index 21e8b72e52..92334bbdc0 100644 --- a/src/test/scala/io/iohk/ethereum/blockchain/sync/BlockBroadcastSpec.scala +++ b/src/test/scala/io/iohk/ethereum/blockchain/sync/BlockBroadcastSpec.scala @@ -5,19 +5,20 @@ import java.net.InetSocketAddress import akka.actor.ActorSystem import akka.testkit.{TestKit, TestProbe} import io.iohk.ethereum.blockchain.sync.regular.BlockBroadcast -import io.iohk.ethereum.{Fixtures, WithActorSystemShutDown} +import io.iohk.ethereum.blockchain.sync.regular.BlockBroadcast.BlockToBroadcast import io.iohk.ethereum.domain.{Block, BlockBody, BlockHeader, ChainWeight} -import io.iohk.ethereum.network.{EtcPeerManagerActor, Peer} -import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo -import io.iohk.ethereum.network.p2p.messages.CommonMessages.{NewBlock, Status} +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} import io.iohk.ethereum.network.p2p.messages.PV62.NewBlockHashes -import io.iohk.ethereum.network.p2p.messages.{PV62, Versions} +import io.iohk.ethereum.network.p2p.messages.PV64.NewBlock +import io.iohk.ethereum.network.p2p.messages.{CommonMessages, PV62, ProtocolVersions} +import io.iohk.ethereum.network.{EtcPeerManagerActor, Peer} import io.iohk.ethereum.utils.Config - -import scala.concurrent.duration._ +import io.iohk.ethereum.{Fixtures, WithActorSystemShutDown} import org.scalatest.flatspec.AnyFlatSpecLike import org.scalatest.matchers.should.Matchers +import scala.concurrent.duration._ + class BlockBroadcastSpec extends TestKit(ActorSystem("BlockBroadcastSpec_System")) with AnyFlatSpecLike @@ -33,7 +34,26 @@ class BlockBroadcastSpec NewBlock(Block(blockHeader, BlockBody(Nil, Nil)), initialPeerInfo.chainWeight.increaseTotalDifficulty(2)) //when - blockBroadcast.broadcastBlock(newBlock, Map(peer -> initialPeerInfo)) + blockBroadcast.broadcastBlock(BlockToBroadcast(newBlock.block, newBlock.chainWeight), Map(peer -> initialPeerInfo)) + + //then + etcPeerManagerProbe.expectMsg(EtcPeerManagerActor.SendMessage(newBlock, peer.id)) + etcPeerManagerProbe.expectMsg(EtcPeerManagerActor.SendMessage(newBlockNewHashes, peer.id)) + etcPeerManagerProbe.expectNoMessage() + } + + it should "send a new block when it is not known by the peer (known by comparing chain weights) (PV63)" in new TestSetup { + //given + //Block that should be sent as it's total difficulty is higher than known by peer + val blockHeader: BlockHeader = baseBlockHeader.copy(number = initialPeerInfo.maxBlockNumber - 3) + val newBlockNewHashes = NewBlockHashes(Seq(PV62.BlockHash(blockHeader.hash, blockHeader.number))) + val peerInfo = initialPeerInfo.copy(remoteStatus = peerStatus.copy(protocolVersion = ProtocolVersions.PV63)) + .withChainWeight(ChainWeight.totalDifficultyOnly(initialPeerInfo.chainWeight.totalDifficulty)) + val newBlock = + CommonMessages.NewBlock(Block(blockHeader, BlockBody(Nil, Nil)), peerInfo.chainWeight.totalDifficulty + 2) + + //when + blockBroadcast.broadcastBlock(BlockToBroadcast(newBlock.block, ChainWeight.totalDifficultyOnly(newBlock.totalDifficulty)), Map(peer -> peerInfo)) //then etcPeerManagerProbe.expectMsg(EtcPeerManagerActor.SendMessage(newBlock, peer.id)) @@ -49,7 +69,7 @@ class BlockBroadcastSpec NewBlock(Block(blockHeader, BlockBody(Nil, Nil)), initialPeerInfo.chainWeight.increaseTotalDifficulty(-2)) //when - blockBroadcast.broadcastBlock(newBlock, Map(peer -> initialPeerInfo)) + blockBroadcast.broadcastBlock(BlockToBroadcast(newBlock.block, newBlock.chainWeight), Map(peer -> initialPeerInfo)) //then etcPeerManagerProbe.expectNoMessage() @@ -63,7 +83,7 @@ class BlockBroadcastSpec NewBlock(Block(blockHeader, BlockBody(Nil, Nil)), initialPeerInfo.chainWeight.increaseTotalDifficulty(-2)) //when - blockBroadcast.broadcastBlock(newBlock, Map(peer -> initialPeerInfo)) + blockBroadcast.broadcastBlock(BlockToBroadcast(newBlock.block, newBlock.chainWeight), Map(peer -> initialPeerInfo)) //then etcPeerManagerProbe.expectMsg(EtcPeerManagerActor.SendMessage(newBlock, peer.id)) @@ -79,7 +99,7 @@ class BlockBroadcastSpec NewBlock(Block(blockHeader, BlockBody(Nil, Nil)), initialPeerInfo.chainWeight.increaseTotalDifficulty(-2)) //when - blockBroadcast.broadcastBlock(newBlock, Map(peer -> initialPeerInfo)) + blockBroadcast.broadcastBlock(BlockToBroadcast(newBlock.block, newBlock.chainWeight), Map(peer -> initialPeerInfo)) //then etcPeerManagerProbe.expectNoMessage() @@ -103,7 +123,7 @@ class BlockBroadcastSpec val peers = Seq(peer, peer2, peer3, peer4) val peersIds = peers.map(_.id) val peersWithInfo = peers.map(_ -> initialPeerInfo).toMap - blockBroadcast.broadcastBlock(firstBlock, peersWithInfo) + blockBroadcast.broadcastBlock(BlockToBroadcast(firstBlock.block, firstBlock.chainWeight), peersWithInfo) //then //Only two peers receive the complete block @@ -128,8 +148,9 @@ class BlockBroadcastSpec val blockHeader: BlockHeader = baseBlockHeader.copy(number = initialPeerInfo.maxBlockNumber + 1) val newBlock = NewBlock(Block(blockHeader, BlockBody(Nil, Nil)), initialPeerInfo.chainWeight.increase(blockHeader)) + val blockToBroadcast = BlockToBroadcast(newBlock.block, newBlock.chainWeight) - blockBroadcast.broadcastBlock(newBlock, Map(peer -> initialPeerInfo)) + blockBroadcast.broadcastBlock(blockToBroadcast, Map(peer -> initialPeerInfo)) etcPeerManagerProbe.expectMsg(EtcPeerManagerActor.SendMessage(newBlock, peer.id)) etcPeerManagerProbe.expectNoMessage(100.millis) @@ -144,8 +165,8 @@ class BlockBroadcastSpec val baseBlockHeader = Fixtures.Blocks.Block3125369.header - val peerStatus = Status( - protocolVersion = Versions.PV63, + val peerStatus = RemoteStatus( + protocolVersion = ProtocolVersions.PV64, networkId = 1, chainWeight = ChainWeight(10, 10000), bestHash = Fixtures.Blocks.Block3125369.header.hash, diff --git a/src/test/scala/io/iohk/ethereum/blockchain/sync/BlockchainHostActorSpec.scala b/src/test/scala/io/iohk/ethereum/blockchain/sync/BlockchainHostActorSpec.scala index 86caf6968d..0f8aec9ceb 100644 --- a/src/test/scala/io/iohk/ethereum/blockchain/sync/BlockchainHostActorSpec.scala +++ b/src/test/scala/io/iohk/ethereum/blockchain/sync/BlockchainHostActorSpec.scala @@ -3,12 +3,13 @@ package io.iohk.ethereum.blockchain.sync import akka.actor.{ActorSystem, Props} import akka.testkit.{TestActorRef, TestProbe} import akka.util.ByteString -import io.iohk.ethereum.domain.{BlockHeader, BlockBody, Receipt} +import io.iohk.ethereum.domain.{BlockBody, BlockHeader, Receipt} import io.iohk.ethereum.mpt.{ExtensionNode, HashNode, HexPrefix, MptNode} import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.MessageFromPeer import io.iohk.ethereum.network.PeerEventBusActor.SubscriptionClassifier.MessageClassifier import io.iohk.ethereum.network.PeerEventBusActor.{PeerSelector, Subscribe} import io.iohk.ethereum.network.PeerManagerActor.{FastSyncHostConfiguration, PeerConfiguration} +import io.iohk.ethereum.network.p2p.messages.Codes import io.iohk.ethereum.network.p2p.messages.PV62._ import io.iohk.ethereum.network.p2p.messages.PV63._ import io.iohk.ethereum.network.p2p.messages.PV63.MptNodeEncoders._ @@ -28,7 +29,7 @@ class BlockchainHostActorSpec extends AnyFlatSpec with Matchers { peerEventBus.expectMsg( Subscribe( MessageClassifier( - Set(GetNodeData.code, GetReceipts.code, GetBlockBodies.code, GetBlockHeaders.code), + Set(Codes.GetNodeDataCode, Codes.GetReceiptsCode, Codes.GetBlockBodiesCode, Codes.GetBlockHeadersCode), PeerSelector.AllPeers ) ) diff --git a/src/test/scala/io/iohk/ethereum/blockchain/sync/PeersClientSpec.scala b/src/test/scala/io/iohk/ethereum/blockchain/sync/PeersClientSpec.scala index 10e7859b04..c368068a4f 100644 --- a/src/test/scala/io/iohk/ethereum/blockchain/sync/PeersClientSpec.scala +++ b/src/test/scala/io/iohk/ethereum/blockchain/sync/PeersClientSpec.scala @@ -6,10 +6,9 @@ import akka.actor.ActorSystem import akka.testkit.TestProbe import akka.util.ByteString import io.iohk.ethereum.domain.ChainWeight -import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} import io.iohk.ethereum.network.Peer -import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status -import io.iohk.ethereum.network.p2p.messages.Versions +import io.iohk.ethereum.network.p2p.messages.ProtocolVersions import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks @@ -64,8 +63,8 @@ class PeersClientSpec extends AnyFlatSpec with Matchers with ScalaCheckPropertyC val peer2 = Peer(new InetSocketAddress("127.0.0.1", 2), TestProbe().ref, false) val peer3 = Peer(new InetSocketAddress("127.0.0.1", 3), TestProbe().ref, false) - private val peerStatus = Status( - protocolVersion = Versions.PV63, + private val peerStatus = RemoteStatus( + protocolVersion = ProtocolVersions.PV63, networkId = 1, chainWeight = ChainWeight(0, 0), bestHash = ByteString.empty, diff --git a/src/test/scala/io/iohk/ethereum/blockchain/sync/PivotBlockSelectorSpec.scala b/src/test/scala/io/iohk/ethereum/blockchain/sync/PivotBlockSelectorSpec.scala index d45561e70f..9ed733720a 100644 --- a/src/test/scala/io/iohk/ethereum/blockchain/sync/PivotBlockSelectorSpec.scala +++ b/src/test/scala/io/iohk/ethereum/blockchain/sync/PivotBlockSelectorSpec.scala @@ -1,24 +1,25 @@ package io.iohk.ethereum.blockchain.sync +import java.net.InetSocketAddress + import akka.actor.{ActorRef, ActorSystem} import akka.testkit.{TestKit, TestProbe} import akka.util.ByteString import com.miguno.akka.testing.VirtualTime +import io.iohk.ethereum.blockchain.sync.fast.PivotBlockSelector import io.iohk.ethereum.blockchain.sync.fast.PivotBlockSelector.{Result, SelectPivotBlock} import io.iohk.ethereum.domain.{BlockHeader, ChainWeight} -import io.iohk.ethereum.network.EtcPeerManagerActor.{HandshakedPeers, PeerInfo} +import io.iohk.ethereum.network.EtcPeerManagerActor.{HandshakedPeers, PeerInfo, RemoteStatus} import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.MessageFromPeer import io.iohk.ethereum.network.PeerEventBusActor.SubscriptionClassifier.{MessageClassifier, PeerDisconnectedClassifier} import io.iohk.ethereum.network.PeerEventBusActor.{PeerSelector, Subscribe, Unsubscribe} import io.iohk.ethereum.network.p2p.Message -import io.iohk.ethereum.network.p2p.messages.CommonMessages.{NewBlock, Status} +import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock import io.iohk.ethereum.network.p2p.messages.PV62._ +import io.iohk.ethereum.network.p2p.messages.{Codes, ProtocolVersions} import io.iohk.ethereum.network.{EtcPeerManagerActor, Peer} import io.iohk.ethereum.utils.Config.SyncConfig import io.iohk.ethereum.{Fixtures, WithActorSystemShutDown} -import java.net.InetSocketAddress - -import io.iohk.ethereum.blockchain.sync.fast.PivotBlockSelector import org.scalatest.BeforeAndAfter import org.scalatest.flatspec.AnyFlatSpecLike import org.scalatest.matchers.should.Matchers @@ -38,9 +39,9 @@ class PivotBlockSelectorSpec pivotBlockSelector ! SelectPivotBlock peerMessageBus.expectMsgAllOf( - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))) + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))) ) etcPeerManager.expectMsgAllOf( @@ -55,9 +56,9 @@ class PivotBlockSelectorSpec pivotBlockSelector ! MessageFromPeer(BlockHeaders(Seq(pivotBlockHeader)), peer3.id) peerMessageBus.expectMsgAllOf( - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))) + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))) ) fastSync.expectMsg(Result(pivotBlockHeader)) @@ -79,9 +80,9 @@ class PivotBlockSelectorSpec pivotBlockSelector ! SelectPivotBlock peerMessageBus.expectMsgAllOf( - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))) + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))) ) etcPeerManager.expectMsgAllOf( @@ -103,9 +104,9 @@ class PivotBlockSelectorSpec time.advance(syncConfig.startRetryInterval) peerMessageBus.expectMsgAllOf( - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))) + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))) ) } @@ -115,9 +116,9 @@ class PivotBlockSelectorSpec pivotBlockSelector ! SelectPivotBlock peerMessageBus.expectMsgAllOf( - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))) + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))) ) etcPeerManager.expectMsgAllOf( @@ -134,9 +135,9 @@ class PivotBlockSelectorSpec pivotBlockSelector ! MessageFromPeer(BlockHeaders(Seq(differentBlockHeader)), peer3.id) peerMessageBus.expectMsgAllOf( - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))), Unsubscribe() ) @@ -145,9 +146,9 @@ class PivotBlockSelectorSpec time.advance(syncConfig.startRetryInterval) peerMessageBus.expectMsgAllOf( - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))) + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))) ) } @@ -157,9 +158,9 @@ class PivotBlockSelectorSpec pivotBlockSelector ! SelectPivotBlock peerMessageBus.expectMsgAllOf( - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))) + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))) ) etcPeerManager.expectMsgAllOf( @@ -175,8 +176,8 @@ class PivotBlockSelectorSpec pivotBlockSelector ! MessageFromPeer(BlockHeaders(Seq(differentBlockHeader)), peer2.id) peerMessageBus.expectMsgAllOf( - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), Unsubscribe() ) @@ -185,9 +186,9 @@ class PivotBlockSelectorSpec time.advance(syncConfig.startRetryInterval) peerMessageBus.expectMsgAllOf( - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))) + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))) ) } @@ -199,7 +200,7 @@ class PivotBlockSelectorSpec pivotBlockSelector ! SelectPivotBlock peerMessageBus.expectMsgAllOf( - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))) + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))) ) etcPeerManager.expectMsgAllOf( @@ -213,7 +214,7 @@ class PivotBlockSelectorSpec ) peerMessageBus.expectMsgAllOf( - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), Unsubscribe() ) time.advance(syncConfig.syncRetryInterval) @@ -231,9 +232,9 @@ class PivotBlockSelectorSpec pivotBlockSelector ! SelectPivotBlock peerMessageBus.expectMsgAllOf( - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))) + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))) ) peerMessageBus.expectNoMessage() @@ -250,9 +251,9 @@ class PivotBlockSelectorSpec pivotBlockSelector ! MessageFromPeer(BlockHeaders(Seq(pivotBlockHeader)), peer3.id) peerMessageBus.expectMsgAllOf( - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))), Unsubscribe() ) peerMessageBus.expectNoMessage() @@ -269,9 +270,9 @@ class PivotBlockSelectorSpec pivotBlockSelector ! SelectPivotBlock peerMessageBus.expectMsgAllOf( - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))) + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))) ) peerMessageBus.expectNoMessage() @@ -288,10 +289,10 @@ class PivotBlockSelectorSpec pivotBlockSelector ! MessageFromPeer(BlockHeaders(Seq(anotherDifferentBlockHeader)), peer3.id) peerMessageBus.expectMsgAllOf( - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer4.id))) // Next peer will be asked + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer4.id))) // Next peer will be asked ) etcPeerManager.expectMsg( @@ -300,7 +301,7 @@ class PivotBlockSelectorSpec pivotBlockSelector ! MessageFromPeer(BlockHeaders(Seq(pivotBlockHeader)), peer4.id) peerMessageBus.expectMsgAllOf( - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer4.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer4.id))), Unsubscribe() ) peerMessageBus.expectNoMessage() @@ -317,9 +318,9 @@ class PivotBlockSelectorSpec pivotBlockSelector ! SelectPivotBlock peerMessageBus.expectMsgAllOf( - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))) + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))) ) peerMessageBus.expectNoMessage() @@ -336,10 +337,10 @@ class PivotBlockSelectorSpec pivotBlockSelector ! MessageFromPeer(BlockHeaders(Seq(anotherDifferentBlockHeader)), peer3.id) peerMessageBus.expectMsgAllOf( - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer4.id))) // Next peer will be asked + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer4.id))) // Next peer will be asked ) etcPeerManager.expectMsg( @@ -348,7 +349,7 @@ class PivotBlockSelectorSpec pivotBlockSelector ! MessageFromPeer(BlockHeaders(Seq(nextAnotherDifferentBlockHeader)), peer4.id) peerMessageBus.expectMsgAllOf( - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer4.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer4.id))), Unsubscribe() ) @@ -357,9 +358,9 @@ class PivotBlockSelectorSpec time.advance(syncConfig.startRetryInterval) peerMessageBus.expectMsgAllOf( - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))) + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))) ) peerMessageBus.expectNoMessage() } @@ -372,9 +373,9 @@ class PivotBlockSelectorSpec pivotBlockSelector ! SelectPivotBlock peerMessageBus.expectMsgAllOf( - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer2.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer4.id))) + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer2.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer4.id))) ) peerMessageBus.expectNoMessage() // Peer 1 will be skipped } @@ -385,10 +386,10 @@ class PivotBlockSelectorSpec pivotBlockSelector ! SelectPivotBlock peerMessageBus.expectMsgAllOf( - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), // Peer 2 is skipped - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))), - Subscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer4.id))) + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))), + Subscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer4.id))) ) peerMessageBus.expectNoMessage() @@ -404,9 +405,9 @@ class PivotBlockSelectorSpec pivotBlockSelector ! MessageFromPeer(BlockHeaders(Seq(pivotBlockHeader)), peer4.id) peerMessageBus.expectMsgAllOf( - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer1.id))), - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer3.id))), - Unsubscribe(MessageClassifier(Set(BlockHeaders.code), PeerSelector.WithId(peer4.id))) + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer1.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer3.id))), + Unsubscribe(MessageClassifier(Set(Codes.BlockHeadersCode), PeerSelector.WithId(peer4.id))) ) fastSync.expectMsg(Result(pivotBlockHeader)) @@ -429,7 +430,7 @@ class PivotBlockSelectorSpec val peerMessageBus = TestProbe() peerMessageBus.ignoreMsg { case Subscribe(MessageClassifier(codes, PeerSelector.AllPeers)) - if codes == Set(NewBlock.code63, NewBlock.code64, NewBlockHashes.code) => + if codes == Set(Codes.NewBlockCode, Codes.NewBlockHashesCode) => true case Subscribe(PeerDisconnectedClassifier(_)) => true case Unsubscribe(Some(PeerDisconnectedClassifier(_))) => true @@ -491,7 +492,7 @@ class PivotBlockSelectorSpec val peer4 = Peer(new InetSocketAddress("127.0.0.4", 0), peer4TestProbe.ref, false) val peer1Status = - Status(1, 1, ChainWeight.totalDifficultyOnly(20), ByteString("peer1_bestHash"), ByteString("unused")) + RemoteStatus(ProtocolVersions.PV64, 1, ChainWeight.totalDifficultyOnly(20), ByteString("peer1_bestHash"), ByteString("unused")) val peer2Status = peer1Status.copy(bestHash = ByteString("peer2_bestHash")) val peer3Status = peer1Status.copy(bestHash = ByteString("peer3_bestHash")) val peer4Status = peer1Status.copy(bestHash = ByteString("peer4_bestHash")) diff --git a/src/test/scala/io/iohk/ethereum/blockchain/sync/StateSyncSpec.scala b/src/test/scala/io/iohk/ethereum/blockchain/sync/StateSyncSpec.scala index af6810ccdc..21ea1b8ce3 100644 --- a/src/test/scala/io/iohk/ethereum/blockchain/sync/StateSyncSpec.scala +++ b/src/test/scala/io/iohk/ethereum/blockchain/sync/StateSyncSpec.scala @@ -8,6 +8,7 @@ import akka.testkit.TestActor.AutoPilot import akka.testkit.{TestKit, TestProbe} import akka.util.ByteString import io.iohk.ethereum.blockchain.sync.StateSyncUtils.{MptNodeData, TrieProvider} +import io.iohk.ethereum.blockchain.sync.fast.SyncStateSchedulerActor._ import io.iohk.ethereum.blockchain.sync.fast.{SyncStateScheduler, SyncStateSchedulerActor} import io.iohk.ethereum.blockchain.sync.fast.SyncStateSchedulerActor.{ RestartRequested, @@ -18,12 +19,11 @@ import io.iohk.ethereum.blockchain.sync.fast.SyncStateSchedulerActor.{ } import io.iohk.ethereum.db.dataSource.RocksDbDataSource.IterationError import io.iohk.ethereum.domain.{Address, BlockchainImpl, ChainWeight} -import io.iohk.ethereum.network.EtcPeerManagerActor.{GetHandshakedPeers, HandshakedPeers, PeerInfo, SendMessage} +import io.iohk.ethereum.network.EtcPeerManagerActor._ import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.MessageFromPeer -import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status import io.iohk.ethereum.network.p2p.messages.PV63.GetNodeData.GetNodeDataEnc import io.iohk.ethereum.network.p2p.messages.PV63.NodeData -import io.iohk.ethereum.network.p2p.messages.Versions +import io.iohk.ethereum.network.p2p.messages.ProtocolVersions import io.iohk.ethereum.network.{Peer, PeerId} import io.iohk.ethereum.utils.Config import io.iohk.ethereum.{Fixtures, ObjectGenerators, WithActorSystemShutDown} @@ -147,8 +147,8 @@ class StateSyncSpec type PeerConfig = Map[PeerId, PeerAction] val syncInit = TestProbe() - val peerStatus = Status( - protocolVersion = Versions.PV63, + val peerStatus = RemoteStatus( + protocolVersion = ProtocolVersions.PV63, networkId = 1, chainWeight = ChainWeight.totalDifficultyOnly(10000), bestHash = Fixtures.Blocks.Block3125369.header.hash, diff --git a/src/test/scala/io/iohk/ethereum/blockchain/sync/SyncControllerSpec.scala b/src/test/scala/io/iohk/ethereum/blockchain/sync/SyncControllerSpec.scala index ca22459ded..a3c3062e89 100644 --- a/src/test/scala/io/iohk/ethereum/blockchain/sync/SyncControllerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/blockchain/sync/SyncControllerSpec.scala @@ -474,7 +474,6 @@ class SyncControllerSpec extends AnyFlatSpec with Matchers with BeforeAndAfter w new SyncController( storagesInstance.storages.appStateStorage, blockchain, - blockchainConfig, storagesInstance.storages.fastSyncStateStorage, ledger, validators, diff --git a/src/test/scala/io/iohk/ethereum/blockchain/sync/TestSyncPeers.scala b/src/test/scala/io/iohk/ethereum/blockchain/sync/TestSyncPeers.scala index 395f181733..e3dd32094b 100644 --- a/src/test/scala/io/iohk/ethereum/blockchain/sync/TestSyncPeers.scala +++ b/src/test/scala/io/iohk/ethereum/blockchain/sync/TestSyncPeers.scala @@ -5,9 +5,9 @@ import akka.actor.ActorSystem import akka.testkit.TestProbe import akka.util.ByteString import io.iohk.ethereum.domain.ChainWeight -import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} import io.iohk.ethereum.network.Peer -import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status +import io.iohk.ethereum.network.p2p.messages.ProtocolVersions trait TestSyncPeers { self: TestSyncConfig => implicit def system: ActorSystem @@ -21,7 +21,7 @@ trait TestSyncPeers { self: TestSyncConfig => val peer3 = Peer(new InetSocketAddress("127.0.0.3", 0), peer3TestProbe.ref, false) val peer1Status = - Status(1, 1, ChainWeight.totalDifficultyOnly(20), ByteString("peer1_bestHash"), ByteString("unused")) + RemoteStatus(ProtocolVersions.PV64, 1, ChainWeight.totalDifficultyOnly(20), ByteString("peer1_bestHash"), ByteString("unused")) val peer2Status = peer1Status.copy(bestHash = ByteString("peer2_bestHash")) val bestBlock = 400000 diff --git a/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/BlockFetcherSpec.scala b/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/BlockFetcherSpec.scala index a080e2434f..2e78d7090b 100644 --- a/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/BlockFetcherSpec.scala +++ b/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/BlockFetcherSpec.scala @@ -1,6 +1,7 @@ package io.iohk.ethereum.blockchain.sync.regular import java.net.InetSocketAddress + import akka.actor.ActorSystem import akka.testkit.{TestKit, TestProbe} import com.miguno.akka.testing.VirtualTime @@ -10,19 +11,14 @@ import io.iohk.ethereum.Fixtures.{Blocks => FixtureBlocks} import io.iohk.ethereum.blockchain.sync.PeersClient.BlacklistPeer import io.iohk.ethereum.blockchain.sync.regular.BlockFetcher.{InternalLastBlockImport, InvalidateBlocksFrom, PickBlocks} import io.iohk.ethereum.blockchain.sync.{PeersClient, TestSyncConfig} -import io.iohk.ethereum.domain.{Block, ChainWeight, HeadersSeq} +import io.iohk.ethereum.domain.{Block, HeadersSeq} import io.iohk.ethereum.network.Peer import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.MessageFromPeer -import io.iohk.ethereum.network.PeerEventBusActor.{PeerSelector, Subscribe} import io.iohk.ethereum.network.PeerEventBusActor.SubscriptionClassifier.MessageClassifier +import io.iohk.ethereum.network.PeerEventBusActor.{PeerSelector, Subscribe} +import io.iohk.ethereum.network.p2p.messages.Codes import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock -import io.iohk.ethereum.network.p2p.messages.PV62.{ - BlockBodies, - BlockHeaders, - GetBlockBodies, - GetBlockHeaders, - NewBlockHashes -} +import io.iohk.ethereum.network.p2p.messages.PV62._ import org.scalatest.freespec.AnyFreeSpecLike import org.scalatest.matchers.should.Matchers @@ -371,7 +367,7 @@ class BlockFetcherSpec extends TestKit(ActorSystem("BlockFetcherSpec_System")) w peerEventBus.expectMsg( Subscribe( MessageClassifier( - Set(NewBlock.code63, NewBlock.code64, NewBlockHashes.code, BlockHeaders.code), + Set(Codes.NewBlockCode, Codes.NewBlockHashesCode, Codes.BlockHeadersCode), PeerSelector.AllPeers ) ) @@ -381,10 +377,10 @@ class BlockFetcherSpec extends TestKit(ActorSystem("BlockFetcherSpec_System")) w // Sending a far away block as a NewBlock message // Currently BlockFetcher only downloads first block-headers-per-request blocks without this def triggerFetching(): Unit = { - val farAwayBlockWeight = ChainWeight.totalDifficultyOnly(100000) + val farAwayBlockTotalDifficulty = 100000 val farAwayBlock = Block(FixtureBlocks.ValidBlock.header.copy(number = 1000), FixtureBlocks.ValidBlock.body) - blockFetcher ! MessageFromPeer(NewBlock(farAwayBlock, farAwayBlockWeight), fakePeer.id) + blockFetcher ! MessageFromPeer(NewBlock(farAwayBlock, farAwayBlockTotalDifficulty), fakePeer.id) } } } diff --git a/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncFixtures.scala b/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncFixtures.scala index b1300496ce..5e0ca38ddd 100644 --- a/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncFixtures.scala +++ b/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncFixtures.scala @@ -16,13 +16,14 @@ import io.iohk.ethereum.consensus.blocks.CheckpointBlockGenerator import io.iohk.ethereum.domain.BlockHeaderImplicits._ import io.iohk.ethereum.domain._ import io.iohk.ethereum.ledger._ -import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.MessageFromPeer import io.iohk.ethereum.network.PeerEventBusActor.Subscribe import io.iohk.ethereum.network.p2p.Message -import io.iohk.ethereum.network.p2p.messages.CommonMessages.{NewBlock, Status} import io.iohk.ethereum.network.p2p.messages.PV62._ import io.iohk.ethereum.network.p2p.messages.PV63.{GetNodeData, NodeData} +import io.iohk.ethereum.network.p2p.messages.PV64.NewBlock +import io.iohk.ethereum.network.p2p.messages.ProtocolVersions import io.iohk.ethereum.network.{Peer, PeerId} import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import io.iohk.ethereum.utils.Config.SyncConfig @@ -49,7 +50,7 @@ trait RegularSyncFixtures { self: Matchers with AsyncMockFactory => implicit override lazy val system: ActorSystem = _system override lazy val syncConfig: SyncConfig = defaultSyncConfig.copy(blockHeadersPerRequest = 2, blockBodiesPerRequest = 2) - val handshakedPeers: PeersMap = (0 to 5).toList.map((peerId _).andThen(getPeer)).fproduct(getPeerInfo).toMap + val handshakedPeers: PeersMap = (0 to 5).toList.map((peerId _).andThen(getPeer)).fproduct(getPeerInfo(_)).toMap val defaultPeer: Peer = peerByNumber(0) val etcPeerManager: TestProbe = TestProbe() @@ -67,7 +68,6 @@ trait RegularSyncFixtures { self: Matchers with AsyncMockFactory => peerEventBus.ref, ledger, blockchain, - blockchainConfig, validators.blockValidator, syncConfig, ommersPool.ref, @@ -101,9 +101,9 @@ trait RegularSyncFixtures { self: Matchers with AsyncMockFactory => def getPeer(id: PeerId): Peer = Peer(new InetSocketAddress("127.0.0.1", 0), TestProbe(id.value).ref, incomingConnection = false) - def getPeerInfo(peer: Peer): PeerInfo = { + def getPeerInfo(peer: Peer, protocolVersion: Int = ProtocolVersions.PV64): PeerInfo = { val status = - Status(1, 1, ChainWeight.totalDifficultyOnly(1), ByteString(s"${peer.id}_bestHash"), ByteString("unused")) + RemoteStatus(protocolVersion, 1, ChainWeight.totalDifficultyOnly(1), ByteString(s"${peer.id}_bestHash"), ByteString("unused")) PeerInfo( status, forkAccepted = true, @@ -316,7 +316,7 @@ trait RegularSyncFixtures { self: Matchers with AsyncMockFactory => def sendLastTestBlockAsTop(): Unit = sendNewBlock(testBlocks.last) def sendNewBlock(block: Block = newBlock, peer: Peer = defaultPeer): Unit = - blockFetcher ! MessageFromPeer(NewBlock(block, ChainWeight(0, block.number)), peer.id) + blockFetcher ! MessageFromPeer(NewBlock(block, ChainWeight.totalDifficultyOnly(block.number)), peer.id) def goToTop(): Unit = { regularSync ! SyncProtocol.Start diff --git a/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncSpec.scala b/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncSpec.scala index ec27efb230..c9fcee4901 100644 --- a/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncSpec.scala +++ b/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncSpec.scala @@ -16,25 +16,22 @@ import io.iohk.ethereum.domain.BlockHeaderImplicits._ import io.iohk.ethereum.domain._ import io.iohk.ethereum.ledger._ import io.iohk.ethereum.mpt.MerklePatriciaTrie.MissingNodeException -import io.iohk.ethereum.network.EtcPeerManagerActor.{GetHandshakedPeers, HandshakedPeers} +import io.iohk.ethereum.network.EtcPeerManagerActor.{GetHandshakedPeers, HandshakedPeers, PeerInfo} import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.MessageFromPeer import io.iohk.ethereum.network.PeerEventBusActor.SubscriptionClassifier.MessageClassifier import io.iohk.ethereum.network.PeerEventBusActor.{PeerSelector, Subscribe} -import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock -import io.iohk.ethereum.domain.BlockHeaderImplicits._ -import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock +import io.iohk.ethereum.network.p2p.messages.{Codes, CommonMessages, ProtocolVersions} import io.iohk.ethereum.network.p2p.messages.PV62._ import io.iohk.ethereum.network.p2p.messages.PV63.{GetNodeData, NodeData} +import io.iohk.ethereum.network.p2p.messages.PV64.NewBlock import io.iohk.ethereum.network.{EtcPeerManagerActor, Peer, PeerEventBusActor} -import io.iohk.ethereum.utils.{BlockchainConfig, Config} import io.iohk.ethereum.utils.Config.SyncConfig -import io.iohk.ethereum.{ObjectGenerators, ResourceFixtures, WordSpecBase} +import io.iohk.ethereum.{BlockHelpers, ObjectGenerators, ResourceFixtures, WordSpecBase} import monix.eval.Task -import io.iohk.ethereum.BlockHelpers import org.scalamock.scalatest.AsyncMockFactory -import org.scalatest.{Assertion, BeforeAndAfterEach} import org.scalatest.diagrams.Diagrams import org.scalatest.matchers.should.Matchers +import org.scalatest.{Assertion, BeforeAndAfterEach} import scala.concurrent.duration._ import scala.concurrent.{Await, ExecutionContext, Future, Promise} @@ -74,7 +71,7 @@ class RegularSyncSpec peerEventBus.expectMsg( PeerEventBusActor.Subscribe( MessageClassifier( - Set(NewBlock.code63, NewBlock.code64, NewBlockHashes.code, BlockHeaders.code), + Set(Codes.NewBlockCode, Codes.NewBlockHashesCode, Codes.BlockHeadersCode), PeerSelector.AllPeers ) ) @@ -451,7 +448,7 @@ class RegularSyncSpec etcPeerManager.fishForSpecificMessageMatching() { case EtcPeerManagerActor.SendMessage(message, _) => message.underlyingMsg match { - case NewBlock(_, block, _) if block == newBlock => true + case NewBlock(block, _) if block == newBlock => true case _ => false } case _ => false @@ -521,7 +518,7 @@ class RegularSyncSpec etcPeerManager.fishForSpecificMessageMatching() { case EtcPeerManagerActor.SendMessage(message, _) => message.underlyingMsg match { - case NewBlock(_, block, _) if block == newBlock => true + case NewBlock(block, _) if block == newBlock => true case _ => false } case _ => false @@ -585,7 +582,7 @@ class RegularSyncSpec etcPeerManager.fishForSpecificMessageMatching() { case EtcPeerManagerActor.SendMessage(message, _) => message.underlyingMsg match { - case NewBlock(_, block, _) if block == checkpointBlock => true + case NewBlock(block, _) if block == checkpointBlock => true case _ => false } case _ => false @@ -594,23 +591,26 @@ class RegularSyncSpec } "broadcasting blocks" should { - // FIXME: this should reflect peers capabilities after ETCM-280 - "send a NewBlock message without latest checkpoint number when before ECIP-1097" in sync( + "send a NewBlock message without latest checkpoint number when client not support PV64" in sync( new OnTopFixture(testSystem) { - override lazy val blockchainConfig: BlockchainConfig = - Config.blockchains.blockchainConfig.copy(ecip1097BlockNumber = newBlock.number + 1) - goToTop() + val peerWithPV63: (Peer, PeerInfo) = { + val id = peerId(handshakedPeers.size) + val peer = getPeer(id) + val peerInfo = getPeerInfo(peer, ProtocolVersions.PV63) + (peer, peerInfo) + } + etcPeerManager.expectMsg(GetHandshakedPeers) - etcPeerManager.reply(HandshakedPeers(handshakedPeers)) + etcPeerManager.reply(HandshakedPeers(Map(peerWithPV63._1 -> peerWithPV63._2))) - sendNewBlock() + blockFetcher ! MessageFromPeer(CommonMessages.NewBlock(newBlock, newBlock.number), defaultPeer.id) etcPeerManager.fishForSpecificMessageMatching() { case EtcPeerManagerActor.SendMessage(message, _) => message.underlyingMsg match { - case NewBlock(NewBlock.code63, `newBlock`, _) => true + case CommonMessages.NewBlock(`newBlock`, _) => true case _ => false } case _ => false @@ -618,12 +618,8 @@ class RegularSyncSpec } ) - // FIXME: this should reflect peers capabilities after ETCM-280 - "send a NewBlock message with latest checkpoint number when after ECIP-1097" in sync( + "send a NewBlock message with latest checkpoint number when client supports PV64" in sync( new OnTopFixture(testSystem) { - override lazy val blockchainConfig: BlockchainConfig = - Config.blockchains.blockchainConfig.copy(ecip1097BlockNumber = newBlock.number) - goToTop() val num: BigInt = 42 @@ -632,12 +628,12 @@ class RegularSyncSpec etcPeerManager.expectMsg(GetHandshakedPeers) etcPeerManager.reply(HandshakedPeers(handshakedPeers)) - sendNewBlock() + blockFetcher ! MessageFromPeer(NewBlock(newBlock, ChainWeight(num, newBlock.number)), defaultPeer.id) etcPeerManager.fishForSpecificMessageMatching() { case EtcPeerManagerActor.SendMessage(message, _) => message.underlyingMsg match { - case NewBlock(NewBlock.code64, `newBlock`, _) => true + case NewBlock(`newBlock`, _) => true case _ => false } case _ => false diff --git a/src/test/scala/io/iohk/ethereum/db/storage/BlockBodiesStorageSpec.scala b/src/test/scala/io/iohk/ethereum/db/storage/BlockBodiesStorageSpec.scala index f5b6caaa19..1a06dea801 100644 --- a/src/test/scala/io/iohk/ethereum/db/storage/BlockBodiesStorageSpec.scala +++ b/src/test/scala/io/iohk/ethereum/db/storage/BlockBodiesStorageSpec.scala @@ -25,7 +25,7 @@ class BlockBodiesStorageSpec val blocks = newBlocks.distinct val totalStorage = insertBlockBodiesMapping(newBlocks) - blocks.foreach { case NewBlock(_, block, _) => + blocks.foreach { case NewBlock(block, _) => assert(totalStorage.get(block.header.hash).contains(block.body)) } } @@ -39,23 +39,23 @@ class BlockBodiesStorageSpec // Mapping of block bodies is deleted val (toDelete, toLeave) = blocks.splitAt(Gen.choose(0, blocks.size).sample.get) - val batchUpdates = toDelete.foldLeft(storage.emptyBatchUpdate) { case (updates, NewBlock(_, block, _)) => + val batchUpdates = toDelete.foldLeft(storage.emptyBatchUpdate) { case (updates, NewBlock(block, _)) => updates.and(storage.remove(block.header.hash)) } batchUpdates.commit() - toLeave.foreach { case NewBlock(_, block, _) => + toLeave.foreach { case NewBlock(block, _) => assert(storage.get(block.header.hash).contains(block.body)) } - toDelete.foreach { case NewBlock(_, block, _) => assert(storage.get(block.header.hash).isEmpty) } + toDelete.foreach { case NewBlock(block, _) => assert(storage.get(block.header.hash).isEmpty) } } } def insertBlockBodiesMapping(newBlocks: Seq[CommonMessages.NewBlock]): BlockBodiesStorage = { val storage = new BlockBodiesStorage(EphemDataSource()) - val batchUpdates = newBlocks.foldLeft(storage.emptyBatchUpdate) { case (updates, NewBlock(_, block, _)) => + val batchUpdates = newBlocks.foldLeft(storage.emptyBatchUpdate) { case (updates, NewBlock(block, _)) => updates.and(storage.put(block.header.hash, block.body)) } diff --git a/src/test/scala/io/iohk/ethereum/db/storage/ChainWeightStorageSuite.scala b/src/test/scala/io/iohk/ethereum/db/storage/ChainWeightStorageSuite.scala index e4ccc6b753..b607ddaced 100644 --- a/src/test/scala/io/iohk/ethereum/db/storage/ChainWeightStorageSuite.scala +++ b/src/test/scala/io/iohk/ethereum/db/storage/ChainWeightStorageSuite.scala @@ -3,8 +3,8 @@ package io.iohk.ethereum.db.storage import io.iohk.ethereum.ObjectGenerators import io.iohk.ethereum.db.dataSource.EphemDataSource import org.scalacheck.Gen -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks import org.scalatest.funsuite.AnyFunSuite +import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks class ChainWeightStorageSuite extends AnyFunSuite with ScalaCheckPropertyChecks with ObjectGenerators { test("ChainWeightStorage insert") { diff --git a/src/test/scala/io/iohk/ethereum/jsonrpc/DebugServiceSpec.scala b/src/test/scala/io/iohk/ethereum/jsonrpc/DebugServiceSpec.scala index 35ef9b88c4..fb5035a76e 100644 --- a/src/test/scala/io/iohk/ethereum/jsonrpc/DebugServiceSpec.scala +++ b/src/test/scala/io/iohk/ethereum/jsonrpc/DebugServiceSpec.scala @@ -4,14 +4,13 @@ import java.net.InetSocketAddress import akka.actor.ActorSystem import akka.testkit.{TestKit, TestProbe} -import io.iohk.ethereum.{Fixtures, WithActorSystemShutDown} import io.iohk.ethereum.domain.ChainWeight import io.iohk.ethereum.jsonrpc.DebugService.{ListPeersInfoRequest, ListPeersInfoResponse} -import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} import io.iohk.ethereum.network.PeerManagerActor.Peers -import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status -import io.iohk.ethereum.network.p2p.messages.Versions +import io.iohk.ethereum.network.p2p.messages.ProtocolVersions import io.iohk.ethereum.network.{EtcPeerManagerActor, Peer, PeerActor, PeerManagerActor} +import io.iohk.ethereum.{Fixtures, WithActorSystemShutDown} import monix.execution.Scheduler.Implicits.global import org.scalamock.scalatest.MockFactory import org.scalatest.concurrent.ScalaFutures @@ -65,8 +64,8 @@ class DebugServiceSpec val etcPeerManager = TestProbe() val debugService = new DebugService(peerManager.ref, etcPeerManager.ref) - val peerStatus = Status( - protocolVersion = Versions.PV63, + val peerStatus = RemoteStatus( + protocolVersion = ProtocolVersions.PV63, networkId = 1, chainWeight = ChainWeight.totalDifficultyOnly(10000), bestHash = Fixtures.Blocks.Block3125369.header.hash, diff --git a/src/test/scala/io/iohk/ethereum/jsonrpc/JsonRpcControllerSpec.scala b/src/test/scala/io/iohk/ethereum/jsonrpc/JsonRpcControllerSpec.scala index eedef962be..6f1d1aed86 100644 --- a/src/test/scala/io/iohk/ethereum/jsonrpc/JsonRpcControllerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/jsonrpc/JsonRpcControllerSpec.scala @@ -5,17 +5,12 @@ import akka.testkit.TestKit import io.iohk.ethereum.domain.ChainWeight import io.iohk.ethereum.jsonrpc.DebugService.{ListPeersInfoRequest, ListPeersInfoResponse} import io.iohk.ethereum.jsonrpc.NetService.{ListeningResponse, PeerCountResponse, VersionResponse} -import io.iohk.ethereum.jsonrpc.serialization.JsonSerializers.{ - OptionNoneToJNullSerializer, - QuantitiesSerializer, - UnformattedDataJsonSerializer -} +import io.iohk.ethereum.jsonrpc.serialization.JsonSerializers.{OptionNoneToJNullSerializer, QuantitiesSerializer, UnformattedDataJsonSerializer} import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController.JsonRpcConfig import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer import io.iohk.ethereum.jsonrpc.server.ipc.JsonRpcIpcServer -import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo -import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status -import io.iohk.ethereum.network.p2p.messages.Versions +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} +import io.iohk.ethereum.network.p2p.messages.ProtocolVersions import io.iohk.ethereum.{Fixtures, LongPatience, WithActorSystemShutDown} import monix.eval.Task import monix.execution.Scheduler.Implicits.global @@ -116,8 +111,8 @@ class JsonRpcControllerSpec } it should "debug_listPeersInfo" in new JsonRpcControllerFixture { - val peerStatus = Status( - protocolVersion = Versions.PV63, + val peerStatus = RemoteStatus( + protocolVersion = ProtocolVersions.PV63, networkId = 1, chainWeight = ChainWeight.totalDifficultyOnly(10000), bestHash = Fixtures.Blocks.Block3125369.header.hash, diff --git a/src/test/scala/io/iohk/ethereum/network/EtcPeerManagerSpec.scala b/src/test/scala/io/iohk/ethereum/network/EtcPeerManagerSpec.scala index d2b2953624..5e8418f544 100644 --- a/src/test/scala/io/iohk/ethereum/network/EtcPeerManagerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/EtcPeerManagerSpec.scala @@ -14,10 +14,10 @@ import io.iohk.ethereum.network.PeerActor.DisconnectPeer import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.{MessageFromPeer, PeerDisconnected, PeerHandshakeSuccessful} import io.iohk.ethereum.network.PeerEventBusActor.SubscriptionClassifier._ import io.iohk.ethereum.network.PeerEventBusActor.{PeerSelector, Subscribe} -import io.iohk.ethereum.network.p2p.messages.CommonMessages.{NewBlock, Status} +import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock import io.iohk.ethereum.network.p2p.messages.PV62._ -import io.iohk.ethereum.network.p2p.messages.Versions import io.iohk.ethereum.network.p2p.messages.WireProtocol.Disconnect +import io.iohk.ethereum.network.p2p.messages.{Codes, PV64, ProtocolVersions} import io.iohk.ethereum.utils.Config import org.bouncycastle.util.encoders.Hex import org.scalatest.flatspec.AnyFlatSpec @@ -43,17 +43,17 @@ class EtcPeerManagerSpec extends AnyFlatSpec with Matchers { requestSender.expectMsg(HandshakedPeers(Map(peer1 -> peer1Info, peer2 -> peer2Info))) } - it should "update max peer when receiving new block" in new TestSetup { + it should "update max peer when receiving new block PV63" in new TestSetup { peerEventBus.expectMsg(Subscribe(PeerHandshaked)) setupNewPeer(peer1, peer1Probe, peer1Info) //given val newBlockWeight = ChainWeight.totalDifficultyOnly(300) val firstHeader: BlockHeader = baseBlockHeader.copy(number = peer1Info.maxBlockNumber + 4) - val firstBlock = NewBlock(Block(firstHeader, BlockBody(Nil, Nil)), newBlockWeight) + val firstBlock = NewBlock(Block(firstHeader, BlockBody(Nil, Nil)), newBlockWeight.totalDifficulty) val secondHeader: BlockHeader = baseBlockHeader.copy(number = peer2Info.maxBlockNumber + 2) - val secondBlock = NewBlock(Block(secondHeader, BlockBody(Nil, Nil)), newBlockWeight) + val secondBlock = NewBlock(Block(secondHeader, BlockBody(Nil, Nil)), newBlockWeight.totalDifficulty) //when peersInfoHolder ! MessageFromPeer(firstBlock, peer1.id) @@ -67,6 +67,30 @@ class EtcPeerManagerSpec extends AnyFlatSpec with Matchers { requestSender.expectMsg(PeerInfoResponse(Some(expectedPeerInfo))) } + it should "update max peer when receiving new block PV64" in new TestSetup { + peerEventBus.expectMsg(Subscribe(PeerHandshaked)) + setupNewPeer(peer1, peer1Probe, peer1InfoPV64) + + //given + val newBlockWeight = ChainWeight.totalDifficultyOnly(300) + val firstHeader: BlockHeader = baseBlockHeader.copy(number = peer1Info.maxBlockNumber + 4) + val firstBlock = PV64.NewBlock(Block(firstHeader, BlockBody(Nil, Nil)), newBlockWeight) + + val secondHeader: BlockHeader = baseBlockHeader.copy(number = peer2Info.maxBlockNumber + 2) + val secondBlock = PV64.NewBlock(Block(secondHeader, BlockBody(Nil, Nil)), newBlockWeight) + + //when + peersInfoHolder ! MessageFromPeer(firstBlock, peer1.id) + peersInfoHolder ! MessageFromPeer(secondBlock, peer1.id) + + //then + requestSender.send(peersInfoHolder, PeerInfoRequest(peer1.id)) + val expectedPeerInfo = initialPeerInfoPV64 + .withBestBlockData(initialPeerInfo.maxBlockNumber + 4, firstHeader.hash) + .withChainWeight(newBlockWeight) + requestSender.expectMsg(PeerInfoResponse(Some(expectedPeerInfo))) + } + it should "update max peer when receiving block header" in new TestSetup { peerEventBus.expectMsg(Subscribe(PeerHandshaked)) setupNewPeer(peer1, peer1Probe, peer1Info) @@ -108,14 +132,29 @@ class EtcPeerManagerSpec extends AnyFlatSpec with Matchers { setupNewPeer(peer1, peer1Probe, peer1Info) //given - val newBlock = NewBlock(baseBlock, initialPeerInfo.chainWeight.increaseTotalDifficulty(1)) + val newBlock = NewBlock(baseBlock, initialPeerInfo.chainWeight.totalDifficulty + 1) //when peersInfoHolder ! MessageFromPeer(newBlock, peer1.id) //then requestSender.send(peersInfoHolder, PeerInfoRequest(peer1.id)) - requestSender.expectMsg(PeerInfoResponse(Some(peer1Info.withChainWeight(newBlock.chainWeight)))) + requestSender.expectMsg(PeerInfoResponse(Some(peer1Info.withChainWeight(ChainWeight.totalDifficultyOnly(newBlock.totalDifficulty))))) + } + + it should "update the peer chain weight when receiving a PV64.NewBlock" in new TestSetup { + peerEventBus.expectMsg(Subscribe(PeerHandshaked)) + setupNewPeer(peer1, peer1Probe, peer1InfoPV64) + + //given + val newBlock = PV64.NewBlock(baseBlock, initialPeerInfoPV64.chainWeight.increaseTotalDifficulty(1).copy(lastCheckpointNumber = initialPeerInfoPV64.chainWeight.lastCheckpointNumber +1)) + + //when + peersInfoHolder ! MessageFromPeer(newBlock, peer1.id) + + //then + requestSender.send(peersInfoHolder, PeerInfoRequest(peer1.id)) + requestSender.expectMsg(PeerInfoResponse(Some(peer1InfoPV64.withChainWeight(newBlock.chainWeight)))) } it should "update the fork accepted when receiving the fork block" in new TestSetup { @@ -238,13 +277,13 @@ class EtcPeerManagerSpec extends AnyFlatSpec with Matchers { override lazy val blockchainConfig = Config.blockchains.blockchainConfig val forkResolver = new ForkResolver.EtcForkResolver(blockchainConfig.daoForkConfig.get) - val peerStatus = Status( - protocolVersion = Versions.PV63, + val peerStatus = RemoteStatus( + protocolVersion = ProtocolVersions.PV63, networkId = 1, chainWeight = ChainWeight.totalDifficultyOnly(10000), bestHash = Fixtures.Blocks.Block3125369.header.hash, genesisHash = Fixtures.Blocks.Genesis.header.hash - ).as63 + ) val initialPeerInfo = PeerInfo( remoteStatus = peerStatus, @@ -254,11 +293,20 @@ class EtcPeerManagerSpec extends AnyFlatSpec with Matchers { bestBlockHash = peerStatus.bestHash ) + val initialPeerInfoPV64 = PeerInfo( + remoteStatus = peerStatus.copy(protocolVersion = ProtocolVersions.PV64), + chainWeight = peerStatus.chainWeight, + forkAccepted = false, + maxBlockNumber = Fixtures.Blocks.Block3125369.header.number, + bestBlockHash = peerStatus.bestHash + ) + val fakeNodeId = ByteString() val peer1Probe = TestProbe() val peer1 = Peer(new InetSocketAddress("127.0.0.1", 1), peer1Probe.ref, false, Some(fakeNodeId)) val peer1Info = initialPeerInfo.withForkAccepted(false) + val peer1InfoPV64 = initialPeerInfoPV64.withForkAccepted(false) val peer2Probe = TestProbe() val peer2 = Peer(new InetSocketAddress("127.0.0.1", 2), peer2Probe.ref, false, Some(fakeNodeId)) val peer2Info = initialPeerInfo.withForkAccepted(false) @@ -298,7 +346,7 @@ class EtcPeerManagerSpec extends AnyFlatSpec with Matchers { peerEventBus.expectMsg( Subscribe( MessageClassifier( - Set(BlockHeaders.code, NewBlock.code63, NewBlock.code64, NewBlockHashes.code), + Set(Codes.BlockHeadersCode, Codes.NewBlockCode, Codes.NewBlockHashesCode), PeerSelector.WithId(peer.id) ) ) diff --git a/src/test/scala/io/iohk/ethereum/network/PeerActorHandshakingSpec.scala b/src/test/scala/io/iohk/ethereum/network/PeerActorHandshakingSpec.scala index 0b2d539948..1e23cd1400 100644 --- a/src/test/scala/io/iohk/ethereum/network/PeerActorHandshakingSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/PeerActorHandshakingSpec.scala @@ -6,21 +6,21 @@ import akka.actor.{ActorSystem, Props} import akka.testkit.{TestActorRef, TestProbe} import akka.util.ByteString import com.miguno.akka.testing.VirtualTime -import io.iohk.ethereum.{Fixtures, Timeouts} import io.iohk.ethereum.Mocks.{MockHandshakerAlwaysFails, MockHandshakerAlwaysSucceeds} import io.iohk.ethereum.blockchain.sync.EphemBlockchainTestSetup -import io.iohk.ethereum.domain.ChainWeight +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} import io.iohk.ethereum.network.PeerActor.Status.Handshaked import io.iohk.ethereum.network.PeerActor.{ConnectTo, GetStatus, StatusResponse} -import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo import io.iohk.ethereum.network.handshaker.Handshaker.NextMessage import io.iohk.ethereum.network.handshaker._ import io.iohk.ethereum.network.p2p.Message +import io.iohk.ethereum.network.p2p.messages.Capability.Capabilities._ import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status -import io.iohk.ethereum.network.p2p.messages.Versions +import io.iohk.ethereum.network.p2p.messages.ProtocolVersions import io.iohk.ethereum.network.p2p.messages.WireProtocol.{Disconnect, Hello, Pong} import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler import io.iohk.ethereum.utils.Config +import io.iohk.ethereum.{Fixtures, Timeouts} import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers @@ -110,7 +110,7 @@ class PeerActorHandshakingSpec extends AnyFlatSpec with Matchers { rlpxConnectionProbe.reply(RLPxConnectionHandler.ConnectionEstablished(ByteString())) rlpxConnectionProbe.expectMsg(RLPxConnectionHandler.SendMessage(defaultHello)) - peerActorHandshakeRequiresHello ! RLPxConnectionHandler.MessageReceived(defaultStatus) + peerActorHandshakeRequiresHello ! RLPxConnectionHandler.MessageReceived(defaultStatusMsg) //Test that the handshake failed rlpxConnectionProbe.expectMsg(RLPxConnectionHandler.SendMessage(Disconnect(defaultReasonDisconnect))) @@ -168,13 +168,14 @@ class PeerActorHandshakingSpec extends AnyFlatSpec with Matchers { } object DefaultValues { - val defaultStatus = Status( - protocolVersion = Versions.PV63, + val defaultStatusMsg = Status( + protocolVersion = ProtocolVersions.PV63, networkId = 1, - chainWeight = ChainWeight.totalDifficultyOnly(Fixtures.Blocks.Genesis.header.difficulty), + totalDifficulty = Fixtures.Blocks.Genesis.header.difficulty, bestHash = Fixtures.Blocks.Genesis.header.hash, genesisHash = Fixtures.Blocks.Genesis.header.hash ) + val defaultStatus = RemoteStatus(defaultStatusMsg) val defaultBlockNumber = 1000 val defaultForkAccepted = true @@ -191,7 +192,7 @@ class PeerActorHandshakingSpec extends AnyFlatSpec with Matchers { val defaultHello = Hello( p2pVersion = 0, clientId = "notused", - capabilities = Nil, + capabilities = Seq(Eth63Capability), listenPort = 0, nodeId = ByteString.empty ) diff --git a/src/test/scala/io/iohk/ethereum/network/PeerEventBusActorSpec.scala b/src/test/scala/io/iohk/ethereum/network/PeerEventBusActorSpec.scala index 1d87db9854..f830560b92 100644 --- a/src/test/scala/io/iohk/ethereum/network/PeerEventBusActorSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/PeerEventBusActorSpec.scala @@ -7,12 +7,11 @@ import akka.testkit.TestProbe import akka.util.ByteString import io.iohk.ethereum.Fixtures import io.iohk.ethereum.domain.ChainWeight +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.{MessageFromPeer, PeerDisconnected, PeerHandshakeSuccessful} import io.iohk.ethereum.network.PeerEventBusActor.PeerSelector import io.iohk.ethereum.network.PeerEventBusActor.SubscriptionClassifier._ -import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo -import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status -import io.iohk.ethereum.network.p2p.messages.Versions +import io.iohk.ethereum.network.p2p.messages.ProtocolVersions import io.iohk.ethereum.network.p2p.messages.WireProtocol.{Ping, Pong} import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers @@ -242,8 +241,8 @@ class PeerEventBusActorSpec extends AnyFlatSpec with Matchers { val peerEventBusActor = system.actorOf(PeerEventBusActor.props) - val peerStatus = Status( - protocolVersion = Versions.PV63, + val peerStatus = RemoteStatus( + protocolVersion = ProtocolVersions.PV63, networkId = 1, chainWeight = ChainWeight.totalDifficultyOnly(10000), bestHash = Fixtures.Blocks.Block3125369.header.hash, diff --git a/src/test/scala/io/iohk/ethereum/network/PeerManagerSpec.scala b/src/test/scala/io/iohk/ethereum/network/PeerManagerSpec.scala index 0b67104de4..458e82166b 100644 --- a/src/test/scala/io/iohk/ethereum/network/PeerManagerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/PeerManagerSpec.scala @@ -7,15 +7,15 @@ import akka.testkit.{TestActorRef, TestKit, TestProbe} import akka.util.ByteString import com.miguno.akka.testing.VirtualTime import io.iohk.ethereum.domain.{Block, BlockBody, BlockHeader, ChainWeight} -import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} import io.iohk.ethereum.network.PeerActor.{ConnectTo, PeerClosedConnection} import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.PeerDisconnected import io.iohk.ethereum.network.PeerEventBusActor.SubscriptionClassifier.PeerHandshaked import io.iohk.ethereum.network.PeerEventBusActor.{PeerEvent, Publish, Subscribe} import io.iohk.ethereum.network.PeerManagerActor.{GetPeers, PeerConfiguration, Peers, SendMessage} -import io.iohk.ethereum.network.discovery.{DiscoveryConfig, PeerDiscoveryManager, Node} -import io.iohk.ethereum.network.p2p.messages.CommonMessages.{NewBlock, Status} -import io.iohk.ethereum.network.p2p.messages.Versions +import io.iohk.ethereum.network.discovery.{DiscoveryConfig, Node, PeerDiscoveryManager} +import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock +import io.iohk.ethereum.network.p2p.messages.ProtocolVersions import io.iohk.ethereum.network.p2p.messages.WireProtocol.Disconnect import io.iohk.ethereum.utils.Config import io.iohk.ethereum.{Fixtures, NormalPatience} @@ -164,7 +164,7 @@ class PeerManagerSpec val baseBlockHeader: BlockHeader = Fixtures.Blocks.Block3125369.header val header: BlockHeader = baseBlockHeader.copy(number = initialPeerInfo.maxBlockNumber + 4) - val block = NewBlock(Block(header, BlockBody(Nil, Nil)), ChainWeight.totalDifficultyOnly(300)) + val block = NewBlock(Block(header, BlockBody(Nil, Nil)), 300) peerManager ! SendMessage(block, PeerId(probe.ref.path.name)) probe.expectMsg(PeerActor.SendMessage(block)) @@ -271,8 +271,8 @@ class PeerManagerSpec val incomingNodeId3 = ByteString(3) val incomingPeerAddress3 = new InetSocketAddress("127.0.0.4", port) - val peerStatus = Status( - protocolVersion = Versions.PV63, + val peerStatus = RemoteStatus( + protocolVersion = ProtocolVersions.PV63, networkId = 1, chainWeight = ChainWeight.totalDifficultyOnly(10000), bestHash = Fixtures.Blocks.Block3125369.header.hash, diff --git a/src/test/scala/io/iohk/ethereum/network/handshaker/EtcHandshakerSpec.scala b/src/test/scala/io/iohk/ethereum/network/handshaker/EtcHandshakerSpec.scala index 5391008516..9485e8292e 100644 --- a/src/test/scala/io/iohk/ethereum/network/handshaker/EtcHandshakerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/handshaker/EtcHandshakerSpec.scala @@ -1,39 +1,38 @@ package io.iohk.ethereum.network.handshaker +import java.util.concurrent.atomic.AtomicReference + import akka.util.ByteString import io.iohk.ethereum.Fixtures import io.iohk.ethereum.blockchain.sync.EphemBlockchainTestSetup import io.iohk.ethereum.crypto.generateKeyPair import io.iohk.ethereum.db.storage.AppStateStorage import io.iohk.ethereum.domain._ +import io.iohk.ethereum.network.EtcPeerManagerActor.{PeerInfo, RemoteStatus} import io.iohk.ethereum.network.ForkResolver import io.iohk.ethereum.network.PeerManagerActor.PeerConfiguration -import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo import io.iohk.ethereum.network.handshaker.Handshaker.HandshakeComplete.{HandshakeFailure, HandshakeSuccess} -import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status +import io.iohk.ethereum.network.p2p.messages.Capability.Capabilities._ import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status.StatusEnc import io.iohk.ethereum.network.p2p.messages.PV62.GetBlockHeaders.GetBlockHeadersEnc import io.iohk.ethereum.network.p2p.messages.PV62.{BlockHeaders, GetBlockHeaders} -import io.iohk.ethereum.network.p2p.messages.Versions import io.iohk.ethereum.network.p2p.messages.WireProtocol.Hello.HelloEnc -import io.iohk.ethereum.network.p2p.messages.WireProtocol.{Capability, Disconnect, Hello} +import io.iohk.ethereum.network.p2p.messages.WireProtocol.{Disconnect, Hello} +import io.iohk.ethereum.network.p2p.messages.{Capability, CommonMessages, PV64, ProtocolVersions} import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import io.iohk.ethereum.utils._ -import java.util.concurrent.atomic.AtomicReference import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers class EtcHandshakerSpec extends AnyFlatSpec with Matchers { - it should "correctly connect during an apropiate handshake if no fork resolver is used" in new TestSetup - with LocalPeerSetup - with RemotePeerSetup { + it should "correctly connect during an appropriate handshake if no fork resolver is used" in new LocalPeerPV63Setup with RemotePeerPV63Setup { initHandshakerWithoutResolver.nextMessage.map(_.messageToSend) shouldBe Right(localHello: HelloEnc) val handshakerAfterHelloOpt = initHandshakerWithoutResolver.applyMessage(remoteHello) assert(handshakerAfterHelloOpt.isDefined) - handshakerAfterHelloOpt.get.nextMessage.map(_.messageToSend) shouldBe Right(localStatus: StatusEnc) - val handshakerAfterStatusOpt = handshakerAfterHelloOpt.get.applyMessage(remoteStatus) + handshakerAfterHelloOpt.get.nextMessage.map(_.messageToSend) shouldBe Right(localStatusMsg: StatusEnc) + val handshakerAfterStatusOpt = handshakerAfterHelloOpt.get.applyMessage(remoteStatusMsg) assert(handshakerAfterStatusOpt.isDefined) handshakerAfterStatusOpt.get.nextMessage match { @@ -57,64 +56,65 @@ class EtcHandshakerSpec extends AnyFlatSpec with Matchers { } } - it should "send status with total difficulty only before ECIP-1097" in new TestSetup - with LocalPeerSetup - with RemotePeerSetup { - - val bc = blockchainConfig - val handshaker = EtcHandshaker(new MockEtcHandshakerConfiguration { - override val blockchainConfig: BlockchainConfig = - bc.copy(ecip1097BlockNumber = firstBlock.number + 1) - }) + it should "send status with total difficulty only when peer does not support PV64" in new LocalPeerPV63Setup with RemotePeerPV63Setup { val newChainWeight = ChainWeight.zero.increase(genesisBlock.header).increase(firstBlock.header) blockchain.save(firstBlock, Nil, newChainWeight, saveAsBestBlock = true) - val newLocalStatus = - localStatus.copy(chainWeight = newChainWeight, bestHash = firstBlock.header.hash) + val newLocalStatusMsg = + localStatusMsg.copy(totalDifficulty = newChainWeight.totalDifficulty, bestHash = firstBlock.header.hash) - handshaker.nextMessage.map(_.messageToSend) shouldBe Right(localHello: HelloEnc) - val handshakerAfterHelloOpt = handshaker.applyMessage(remoteHello) + initHandshakerWithoutResolver.nextMessage.map(_.messageToSend) shouldBe Right(localHello: HelloEnc) + val handshakerAfterHelloOpt = initHandshakerWithoutResolver.applyMessage(remoteHello) assert(handshakerAfterHelloOpt.isDefined) - handshakerAfterHelloOpt.get.nextMessage.map(_.messageToSend.underlyingMsg) shouldBe Right(newLocalStatus) - } + handshakerAfterHelloOpt.get.nextMessage.map(_.messageToSend.underlyingMsg) shouldBe Right(newLocalStatusMsg) + + val handshakerAfterStatusOpt = handshakerAfterHelloOpt.get.applyMessage(remoteStatusMsg) + handshakerAfterStatusOpt shouldBe 'defined + handshakerAfterStatusOpt.get.nextMessage match { + case Left(HandshakeSuccess(peerInfo)) => + peerInfo.remoteStatus.protocolVersion shouldBe localStatus.protocolVersion - it should "send status with total difficulty and latest checkpoint number after ECIP-1097" in new TestSetup - with LocalPeerSetup - with RemotePeerSetup { + case other => + fail(s"Invalid handshaker state: $other") + } + } - val bc = blockchainConfig - val handshaker = EtcHandshaker(new MockEtcHandshakerConfiguration { - override val blockchainConfig: BlockchainConfig = - bc.copy(ecip1097BlockNumber = firstBlock.number) - }) + it should "send status with total difficulty and latest checkpoint when peer supports PV64" in new LocalPeerPV64Setup with RemotePeerPV64Setup { val newChainWeight = ChainWeight.zero.increase(genesisBlock.header).increase(firstBlock.header) blockchain.save(firstBlock, Nil, newChainWeight, saveAsBestBlock = true) - blockchain.saveBestKnownBlocks(firstBlock.number, Some(42)) // doesn't matter what number this is - val newLocalStatus = - localStatus + val newLocalStatusMsg = + localStatusMsg .copy( chainWeight = newChainWeight, bestHash = firstBlock.header.hash ) - .as64 - handshaker.nextMessage.map(_.messageToSend) shouldBe Right(localHello: HelloEnc) - val handshakerAfterHelloOpt = handshaker.applyMessage(remoteHello) + initHandshakerWithoutResolver.nextMessage.map(_.messageToSend) shouldBe Right(localHello: HelloEnc) + + val handshakerAfterHelloOpt = initHandshakerWithoutResolver.applyMessage(remoteHello) assert(handshakerAfterHelloOpt.isDefined) - handshakerAfterHelloOpt.get.nextMessage.map(_.messageToSend.underlyingMsg) shouldBe Right(newLocalStatus) + handshakerAfterHelloOpt.get.nextMessage.map(_.messageToSend.underlyingMsg) shouldBe Right(newLocalStatusMsg) + + val handshakerAfterStatusOpt = handshakerAfterHelloOpt.get.applyMessage(remoteStatusMsg) + handshakerAfterStatusOpt shouldBe 'defined + handshakerAfterStatusOpt.get.nextMessage match { + case Left(HandshakeSuccess(peerInfo)) => + peerInfo.remoteStatus.protocolVersion shouldBe localStatus.protocolVersion + + case other => + fail(s"Invalid handshaker state: $other") + } } - it should "correctly connect during an apropiate handshake if a fork resolver is used and the remote peer has the DAO block" in new TestSetup - with LocalPeerSetup - with RemotePeerSetup { + it should "correctly connect during an appropriate handshake if a fork resolver is used and the remote peer has the DAO block" in new LocalPeerSetup with RemotePeerPV63Setup { val handshakerAfterHelloOpt = initHandshakerWithResolver.applyMessage(remoteHello) - val handshakerAfterStatusOpt = handshakerAfterHelloOpt.get.applyMessage(remoteStatus) + val handshakerAfterStatusOpt = handshakerAfterHelloOpt.get.applyMessage(remoteStatusMsg) assert(handshakerAfterStatusOpt.isDefined) handshakerAfterStatusOpt.get.nextMessage.map(_.messageToSend) shouldBe Right( localGetBlockHeadersRequest: GetBlockHeadersEnc @@ -143,12 +143,10 @@ class EtcHandshakerSpec extends AnyFlatSpec with Matchers { } } - it should "correctly connect during an apropiate handshake if a fork resolver is used and the remote peer doesn't have the DAO block" in new TestSetup - with LocalPeerSetup - with RemotePeerSetup { + it should "correctly connect during an appropriate handshake if a fork resolver is used and the remote peer doesn't have the DAO block" in new LocalPeerSetup with RemotePeerPV63Setup { val handshakerAfterHelloOpt = initHandshakerWithResolver.applyMessage(remoteHello) - val handshakerAfterStatusOpt = handshakerAfterHelloOpt.get.applyMessage(remoteStatus) + val handshakerAfterStatusOpt = handshakerAfterHelloOpt.get.applyMessage(remoteStatusMsg) assert(handshakerAfterStatusOpt.isDefined) handshakerAfterStatusOpt.get.nextMessage.map(_.messageToSend) shouldBe Right( localGetBlockHeadersRequest: GetBlockHeadersEnc @@ -177,18 +175,14 @@ class EtcHandshakerSpec extends AnyFlatSpec with Matchers { } } - it should "fail if a timeout happened during hello exchange" in new TestSetup - with LocalPeerSetup - with RemotePeerSetup { + it should "fail if a timeout happened during hello exchange" in new TestSetup { val handshakerAfterTimeout = initHandshakerWithoutResolver.processTimeout handshakerAfterTimeout.nextMessage.map(_.messageToSend) shouldBe Left( HandshakeFailure(Disconnect.Reasons.TimeoutOnReceivingAMessage) ) } - it should "fail if a timeout happened during status exchange" in new TestSetup - with LocalPeerSetup - with RemotePeerSetup { + it should "fail if a timeout happened during status exchange" in new RemotePeerPV63Setup { val handshakerAfterHelloOpt = initHandshakerWithResolver.applyMessage(remoteHello) val handshakerAfterTimeout = handshakerAfterHelloOpt.get.processTimeout handshakerAfterTimeout.nextMessage.map(_.messageToSend) shouldBe Left( @@ -196,45 +190,39 @@ class EtcHandshakerSpec extends AnyFlatSpec with Matchers { ) } - it should "fail if a timeout happened during fork block exchange" in new TestSetup - with LocalPeerSetup - with RemotePeerSetup { + it should "fail if a timeout happened during fork block exchange" in new RemotePeerPV63Setup { val handshakerAfterHelloOpt = initHandshakerWithResolver.applyMessage(remoteHello) - val handshakerAfterStatusOpt = handshakerAfterHelloOpt.get.applyMessage(remoteStatus) + val handshakerAfterStatusOpt = handshakerAfterHelloOpt.get.applyMessage(remoteStatusMsg) val handshakerAfterTimeout = handshakerAfterStatusOpt.get.processTimeout handshakerAfterTimeout.nextMessage.map(_.messageToSend) shouldBe Left( HandshakeFailure(Disconnect.Reasons.TimeoutOnReceivingAMessage) ) } - it should "fail if a status msg is received with invalid network id" in new TestSetup - with LocalPeerSetup - with RemotePeerSetup { + it should "fail if a status msg is received with invalid network id" in new LocalPeerPV63Setup with RemotePeerPV63Setup { val wrongNetworkId = localStatus.networkId + 1 val handshakerAfterHelloOpt = initHandshakerWithResolver.applyMessage(remoteHello) val handshakerAfterStatusOpt = - handshakerAfterHelloOpt.get.applyMessage(remoteStatus.copy(networkId = wrongNetworkId)) + handshakerAfterHelloOpt.get.applyMessage(remoteStatusMsg.copy(networkId = wrongNetworkId)) handshakerAfterStatusOpt.get.nextMessage.map(_.messageToSend) shouldBe Left( HandshakeFailure(Disconnect.Reasons.DisconnectRequested) ) } - it should "fail if a status msg is received with invalid genesisHash" in new TestSetup - with LocalPeerSetup - with RemotePeerSetup { + it should "fail if a status msg is received with invalid genesisHash" in new LocalPeerPV63Setup with RemotePeerPV63Setup { val wrongGenesisHash = (localStatus.genesisHash.head + 1).toByte +: localStatus.genesisHash.tail val handshakerAfterHelloOpt = initHandshakerWithResolver.applyMessage(remoteHello) val handshakerAfterStatusOpt = - handshakerAfterHelloOpt.get.applyMessage(remoteStatus.copy(genesisHash = wrongGenesisHash)) + handshakerAfterHelloOpt.get.applyMessage(remoteStatusMsg.copy(genesisHash = wrongGenesisHash)) handshakerAfterStatusOpt.get.nextMessage.map(_.messageToSend) shouldBe Left( HandshakeFailure(Disconnect.Reasons.DisconnectRequested) ) } - it should "fail if the remote peer doesn't support PV63" in new TestSetup with LocalPeerSetup with RemotePeerSetup { - val pv62Capability = Capability("eth", Versions.PV62.toByte) + it should "fail if the remote peer doesn't support PV63/PV64" in new RemotePeerPV63Setup { + val pv62Capability = Capability("eth", ProtocolVersions.PV62.toByte) val handshakerAfterHelloOpt = initHandshakerWithResolver.applyMessage(remoteHello.copy(capabilities = Seq(pv62Capability))) assert(handshakerAfterHelloOpt.isDefined) @@ -243,11 +231,9 @@ class EtcHandshakerSpec extends AnyFlatSpec with Matchers { ) } - it should "fail if a fork resolver is used and the block from the remote peer isn't accepted" in new TestSetup - with LocalPeerSetup - with RemotePeerSetup { + it should "fail if a fork resolver is used and the block from the remote peer isn't accepted" in new RemotePeerPV63Setup { val handshakerAfterHelloOpt = initHandshakerWithResolver.applyMessage(remoteHello) - val handshakerAfterStatusOpt = handshakerAfterHelloOpt.get.applyMessage(remoteStatus) + val handshakerAfterStatusOpt = handshakerAfterHelloOpt.get.applyMessage(remoteStatusMsg) val handshakerAfterForkBlockOpt = handshakerAfterStatusOpt.get.applyMessage( BlockHeaders(Seq(genesisBlock.header.copy(number = forkBlockHeader.number))) ) @@ -275,13 +261,13 @@ class EtcHandshakerSpec extends AnyFlatSpec with Matchers { ) lazy val nodeStatusHolder = new AtomicReference(nodeStatus) - class MockEtcHandshakerConfiguration extends EtcHandshakerConfiguration { + class MockEtcHandshakerConfiguration(pv: Int = Config.Network.protocolVersion) extends EtcHandshakerConfiguration { override val forkResolverOpt: Option[ForkResolver] = None override val nodeStatusHolder: AtomicReference[NodeStatus] = TestSetup.this.nodeStatusHolder override val peerConfiguration: PeerConfiguration = Config.Network.peer override val blockchain: Blockchain = TestSetup.this.blockchain - override val blockchainConfig: BlockchainConfig = TestSetup.this.blockchainConfig override val appStateStorage: AppStateStorage = TestSetup.this.storagesInstance.storages.appStateStorage + override val protocolVersion: Int = pv } val etcHandshakerConfigurationWithResolver = new MockEtcHandshakerConfiguration { @@ -290,7 +276,7 @@ class EtcHandshakerSpec extends AnyFlatSpec with Matchers { ) } - val initHandshakerWithoutResolver = EtcHandshaker(new MockEtcHandshakerConfiguration) + val initHandshakerWithoutResolver = EtcHandshaker(new MockEtcHandshakerConfiguration(ProtocolVersions.PV64)) val initHandshakerWithResolver = EtcHandshaker(etcHandshakerConfigurationWithResolver) val firstBlock = @@ -301,21 +287,35 @@ class EtcHandshakerSpec extends AnyFlatSpec with Matchers { val localHello = Hello( p2pVersion = EtcHelloExchangeState.P2pVersion, clientId = Config.clientId, - capabilities = Seq(Capability("eth", Versions.PV63.toByte)), + capabilities = Seq(Etc64Capability, Eth63Capability), listenPort = 0, //Local node not listening nodeId = ByteString(nodeStatus.nodeId) ) - val localStatus = Status( - protocolVersion = Versions.PV63, + val localGetBlockHeadersRequest = + GetBlockHeaders(Left(forkBlockHeader.number), maxHeaders = 1, skip = 0, reverse = false) + } + + trait LocalPeerPV63Setup extends LocalPeerSetup { + val localStatusMsg = CommonMessages.Status( + protocolVersion = ProtocolVersions.PV63, networkId = Config.Network.peer.networkId, - chainWeight = ChainWeight.zero.increase(genesisBlock.header), + totalDifficulty = genesisBlock.header.difficulty, bestHash = genesisBlock.header.hash, genesisHash = genesisBlock.header.hash - ).as63 + ) + val localStatus = RemoteStatus(localStatusMsg) + } - val localGetBlockHeadersRequest = - GetBlockHeaders(Left(forkBlockHeader.number), maxHeaders = 1, skip = 0, reverse = false) + trait LocalPeerPV64Setup extends LocalPeerSetup { + val localStatusMsg = PV64.Status( + protocolVersion = ProtocolVersions.PV64, + networkId = Config.Network.peer.networkId, + chainWeight = ChainWeight.zero.increase(genesisBlock.header), + bestHash = genesisBlock.header.hash, + genesisHash = genesisBlock.header.hash + ) + val localStatus = RemoteStatus(localStatusMsg) } trait RemotePeerSetup extends TestSetup { @@ -325,22 +325,44 @@ class EtcHandshakerSpec extends AnyFlatSpec with Matchers { discoveryStatus = ServerStatus.NotListening ) val remotePort = 8545 + } + + trait RemotePeerPV63Setup extends RemotePeerSetup { + val remoteHello = Hello( + p2pVersion = EtcHelloExchangeState.P2pVersion, + clientId = "remote-peer", + capabilities = Seq(Eth63Capability), + listenPort = remotePort, + nodeId = ByteString(remoteNodeStatus.nodeId) + ) + + val remoteStatusMsg = CommonMessages.Status( + protocolVersion = ProtocolVersions.PV63, + networkId = Config.Network.peer.networkId, + totalDifficulty = 0, + bestHash = genesisBlock.header.hash, + genesisHash = genesisBlock.header.hash + ) + val remoteStatus = RemoteStatus(remoteStatusMsg) + } + + trait RemotePeerPV64Setup extends RemotePeerSetup { val remoteHello = Hello( p2pVersion = EtcHelloExchangeState.P2pVersion, clientId = "remote-peer", - capabilities = Seq(Capability("eth", Versions.PV63.toByte)), + capabilities = Seq(Etc64Capability, Eth63Capability), listenPort = remotePort, nodeId = ByteString(remoteNodeStatus.nodeId) ) - val remoteStatus = - Status( - protocolVersion = Versions.PV63, + val remoteStatusMsg = + PV64.Status( + protocolVersion = ProtocolVersions.PV64, networkId = Config.Network.peer.networkId, chainWeight = ChainWeight.zero, bestHash = genesisBlock.header.hash, genesisHash = genesisBlock.header.hash - ).as63 + ) } } diff --git a/src/test/scala/io/iohk/ethereum/network/p2p/MessageCodecSpec.scala b/src/test/scala/io/iohk/ethereum/network/p2p/MessageCodecSpec.scala index dc319ec869..0b37a54e4d 100644 --- a/src/test/scala/io/iohk/ethereum/network/p2p/MessageCodecSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/p2p/MessageCodecSpec.scala @@ -1,11 +1,11 @@ package io.iohk.ethereum.network.p2p import akka.util.ByteString -import io.iohk.ethereum.domain.ChainWeight import io.iohk.ethereum.network.handshaker.EtcHelloExchangeState +import io.iohk.ethereum.network.p2p.messages.Capability.Capabilities._ import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status -import io.iohk.ethereum.network.p2p.messages.Versions -import io.iohk.ethereum.network.p2p.messages.WireProtocol.{Capability, Hello} +import io.iohk.ethereum.network.p2p.messages.ProtocolVersions +import io.iohk.ethereum.network.p2p.messages.WireProtocol.Hello import io.iohk.ethereum.network.rlpx.{FrameCodec, MessageCodec} import io.iohk.ethereum.utils.Config import org.scalatest.flatspec.AnyFlatSpec @@ -15,7 +15,7 @@ class MessageCodecSpec extends AnyFlatSpec with Matchers { it should "not compress messages when remote side advertises p2p version less than 5" in new TestSetup { val remoteHello = remoteMessageCodec.encodeMessage(helloV4) - val localReceviveRemoteHello = messageCodec.readMessages(remoteHello) + val localReceivedRemoteHello = messageCodec.readMessages(remoteHello) val localNextMessageAfterHello = messageCodec.encodeMessage(status) val remoteReadNotCompressedStatus = remoteMessageCodec.readMessages(localNextMessageAfterHello) @@ -27,7 +27,7 @@ class MessageCodecSpec extends AnyFlatSpec with Matchers { it should "compress messages when remote side advertises p2p version larger or equal 5" in new TestSetup { val remoteHello = remoteMessageCodec.encodeMessage(helloV5) - val localReceviveRemoteHello = messageCodec.readMessages(remoteHello) + val localReceivedRemoteHello = messageCodec.readMessages(remoteHello) val localNextMessageAfterHello = messageCodec.encodeMessage(status) val remoteReadNotCompressedStatus = remoteMessageCodec.readMessages(localNextMessageAfterHello) @@ -40,7 +40,7 @@ class MessageCodecSpec extends AnyFlatSpec with Matchers { it should "compress messages when both sides advertises p2p version larger or equal 5" in new TestSetup { val remoteHello = remoteMessageCodec.encodeMessage(helloV5) - val localReceviveRemoteHello = messageCodec.readMessages(remoteHello) + val localReceivedRemoteHello = messageCodec.readMessages(remoteHello) val localHello = messageCodec.encodeMessage(helloV5) val remoteReceivedLocalHello = remoteMessageCodec.readMessages(localHello) @@ -55,7 +55,7 @@ class MessageCodecSpec extends AnyFlatSpec with Matchers { it should "compress and decompress first message after hello when receiving 2 frames" in new TestSetup { val remoteHello = remoteMessageCodec.encodeMessage(helloV5) - val localReceviveRemoteHello = messageCodec.readMessages(remoteHello) + val localReceivedRemoteHello = messageCodec.readMessages(remoteHello) // hello won't be compressed as per spec it never is, and status will be compressed as remote peer advertised proper versions val localHello = messageCodec.encodeMessage(helloV5) @@ -77,7 +77,7 @@ class MessageCodecSpec extends AnyFlatSpec with Matchers { val helloV5 = Hello( p2pVersion = EtcHelloExchangeState.P2pVersion, clientId = Config.clientId, - capabilities = Seq(Capability("eth", Versions.PV63.toByte)), + capabilities = Seq(Eth63Capability), listenPort = 0, //Local node not listening nodeId = ByteString(1) ) @@ -85,15 +85,17 @@ class MessageCodecSpec extends AnyFlatSpec with Matchers { val helloV4 = helloV5.copy(p2pVersion = 4) val status = Status( - protocolVersion = Versions.PV63, + protocolVersion = ProtocolVersions.PV63, networkId = Config.Network.peer.networkId, - chainWeight = ChainWeight.totalDifficultyOnly(1), + totalDifficulty = 1, bestHash = ByteString(1), genesisHash = ByteString(1) ) - val messageCodec = new MessageCodec(frameCodec, EthereumMessageDecoder, Versions.PV63) - val remoteMessageCodec = new MessageCodec(remoteFrameCodec, EthereumMessageDecoder, Versions.PV63) + val decoder = NetworkMessageDecoder orElse EthereumMessageDecoder + + val messageCodec = new MessageCodec(frameCodec, decoder, ProtocolVersions.PV63) + val remoteMessageCodec = new MessageCodec(remoteFrameCodec, decoder, ProtocolVersions.PV63) } diff --git a/src/test/scala/io/iohk/ethereum/network/p2p/MessageDecodersSpec.scala b/src/test/scala/io/iohk/ethereum/network/p2p/MessageDecodersSpec.scala new file mode 100644 index 0000000000..dc53f75079 --- /dev/null +++ b/src/test/scala/io/iohk/ethereum/network/p2p/MessageDecodersSpec.scala @@ -0,0 +1,223 @@ +package io.iohk.ethereum.network.p2p + +import akka.util.ByteString +import io.iohk.ethereum.{Fixtures, ObjectGenerators} +import io.iohk.ethereum.domain.ChainWeight +import io.iohk.ethereum.network.p2p.messages.Capability.Capabilities._ +import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions +import io.iohk.ethereum.network.p2p.messages._ +import io.iohk.ethereum.nodebuilder.SecureRandomBuilder +import org.bouncycastle.util.encoders.Hex +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers + +class MessageDecodersSpec extends AnyFlatSpec with Matchers with SecureRandomBuilder { + + val decode = EthereumMessageDecoder.fromBytes _ + + val exampleHash = ByteString(Hex.decode("fccdbfe911f9df0a6cc0107d1240f76dfdd1d301b65fdc3cd2ae62752affbef6")) + + val blockHashesFromNumberBytes: Array[Byte] = Hex.decode("c20c28") + + val NewBlockHashesPV61bytes: Array[Byte] = + Hex.decode( + "f842a0fccdbfe911f9df0a6cc0107d1240f76dfdd1d301b65fdc3cd2ae62752affbef6a0fccdbfe911f9df0a6cc0107d1240f76dfdd1d301b65fdc3cd2ae62752affbef6" + ) + + "MessageDecoders" should "decode wire protocol message for all versions of protocol" in { + val helloBytes: Array[Byte] = + Hex.decode( + "f85404866d616e746973c6c5836574683f820d05b840a13f3f0555b5037827c743e40fce29139fcf8c3f2a8f12753872fe906a77ff70f6a7f517be995805ff39ab73af1d53dac1a6c9786eebc5935fc455ac8f41ba67" + ) + val hello = WireProtocol.Hello( + p2pVersion = 4, + clientId = "mantis", + capabilities = Seq(Eth63Capability), + listenPort = 3333, + nodeId = ByteString( + Hex.decode( + "a13f3f0555b5037827c743e40fce29139fcf8c3f2a8f12753872fe906a77ff70f6a7f517be995805ff39ab73af1d53dac1a6c9786eebc5935fc455ac8f41ba67" + ) + ) + ) + NetworkMessageDecoder.fromBytes(WireProtocol.Hello.code, helloBytes, ProtocolVersions.PV61) shouldBe hello + NetworkMessageDecoder.fromBytes(WireProtocol.Hello.code, helloBytes, ProtocolVersions.PV62) shouldBe hello + NetworkMessageDecoder.fromBytes(WireProtocol.Hello.code, helloBytes, ProtocolVersions.PV63) shouldBe hello + NetworkMessageDecoder.fromBytes(WireProtocol.Hello.code, helloBytes, ProtocolVersions.PV64) shouldBe hello + } + + it should "decode NewBlockHashes message for all supported versions of protocol" in { + val newBlockHashesPV61 = PV61.NewBlockHashes(Seq(exampleHash, exampleHash)) + + val NewBlockHashesPV62bytes: Array[Byte] = + Hex.decode( + "f846e2a0fccdbfe911f9df0a6cc0107d1240f76dfdd1d301b65fdc3cd2ae62752affbef601e2a0fccdbfe911f9df0a6cc0107d1240f76dfdd1d301b65fdc3cd2ae62752affbef602" + ) + val newBlockHashesPV62 = PV62.NewBlockHashes(Seq(PV62.BlockHash(exampleHash, 1), PV62.BlockHash(exampleHash, 2))) + + decode(Codes.NewBlockHashesCode, NewBlockHashesPV61bytes, ProtocolVersions.PV61) shouldBe newBlockHashesPV61 + decode(Codes.NewBlockHashesCode, NewBlockHashesPV62bytes, ProtocolVersions.PV62) shouldBe newBlockHashesPV62 + decode(Codes.NewBlockHashesCode, NewBlockHashesPV62bytes, ProtocolVersions.PV63) shouldBe newBlockHashesPV62 + decode(Codes.NewBlockHashesCode, NewBlockHashesPV62bytes, ProtocolVersions.PV64) shouldBe newBlockHashesPV62 + } + + it should "not decode message from older version of protocol as newer version" in { + assertThrows[RuntimeException] { + decode(Codes.NewBlockHashesCode, NewBlockHashesPV61bytes, ProtocolVersions.PV62) + } + } + + it should "decode BlockHashesFromNumber message for all supported versions of protocol" in { + val blockHashesFromNumber = PV61.BlockHashesFromNumber(12, 40) + decode(Codes.BlockHashesFromNumberCode, blockHashesFromNumberBytes, ProtocolVersions.PV61) shouldBe blockHashesFromNumber + } + + it should "decode GetBlockHeaders message for all supported versions of protocol" in { + val getBlockHeaders = PV62.GetBlockHeaders(Left(1), 1, 1, false) + val getBlockHeadersBytes: Array[Byte] = getBlockHeaders.toBytes + + assertThrows[RuntimeException] { + decode(Codes.GetBlockHeadersCode, getBlockHeadersBytes, ProtocolVersions.PV61) + } + decode(Codes.GetBlockHeadersCode, getBlockHeadersBytes, ProtocolVersions.PV62) shouldBe getBlockHeaders + decode(Codes.GetBlockHeadersCode, getBlockHeadersBytes, ProtocolVersions.PV63) shouldBe getBlockHeaders + decode(Codes.GetBlockHeadersCode, getBlockHeadersBytes, ProtocolVersions.PV64) shouldBe getBlockHeaders + } + + it should "decode BlockHeaders message for all supported versions of protocol" in { + val blockHeaders = PV62.BlockHeaders(ObjectGenerators.seqBlockHeaderGen.sample.get) + val blockHeadersBytes: Array[Byte] = blockHeaders.toBytes + + assertThrows[RuntimeException] { + decode(Codes.BlockHeadersCode, blockHeadersBytes, ProtocolVersions.PV61) + } + decode(Codes.BlockHeadersCode, blockHeadersBytes, ProtocolVersions.PV62) shouldBe blockHeaders + decode(Codes.BlockHeadersCode, blockHeadersBytes, ProtocolVersions.PV63) shouldBe blockHeaders + decode(Codes.BlockHeadersCode, blockHeadersBytes, ProtocolVersions.PV64) shouldBe blockHeaders + } + + it should "decode GetBlockBodies message for all supported versions of protocol" in { + val getBlockBodies = PV62.GetBlockBodies(Seq(exampleHash)) + val getBlockBodiesBytes: Array[Byte] = getBlockBodies.toBytes + + assertThrows[RuntimeException] { + decode(Codes.GetBlockBodiesCode, getBlockBodiesBytes, ProtocolVersions.PV61) + } + decode(Codes.GetBlockBodiesCode, getBlockBodiesBytes, ProtocolVersions.PV62) shouldBe getBlockBodies + decode(Codes.GetBlockBodiesCode, getBlockBodiesBytes, ProtocolVersions.PV63) shouldBe getBlockBodies + decode(Codes.GetBlockBodiesCode, getBlockBodiesBytes, ProtocolVersions.PV64) shouldBe getBlockBodies + } + + it should "decode BlockBodies message for all supported versions of protocol" in { + val blockBodies = PV62.BlockBodies(Seq(Fixtures.Blocks.Block3125369.body, Fixtures.Blocks.DaoForkBlock.body)) + val blockBodiesBytes: Array[Byte] = blockBodies.toBytes + + assertThrows[RuntimeException] { + decode(Codes.BlockBodiesCode, blockBodiesBytes, ProtocolVersions.PV61) + } + decode(Codes.BlockBodiesCode, blockBodiesBytes, ProtocolVersions.PV62) shouldBe blockBodies + decode(Codes.BlockBodiesCode, blockBodiesBytes, ProtocolVersions.PV63) shouldBe blockBodies + decode(Codes.BlockBodiesCode, blockBodiesBytes, ProtocolVersions.PV64) shouldBe blockBodies + } + + it should "decode GetNodeData message for all supported versions of protocol" in { + val getNodeData = PV63.GetNodeData(Seq(exampleHash)) + val getNodeDataBytes: Array[Byte] = getNodeData.toBytes + + assertThrows[RuntimeException] { + decode(Codes.GetNodeDataCode, getNodeDataBytes, ProtocolVersions.PV61) + } + assertThrows[RuntimeException] { + decode(Codes.GetNodeDataCode, getNodeDataBytes, ProtocolVersions.PV62) + } + decode(Codes.GetNodeDataCode, getNodeDataBytes, ProtocolVersions.PV63) shouldBe getNodeData + decode(Codes.GetNodeDataCode, getNodeDataBytes, ProtocolVersions.PV64) shouldBe getNodeData + } + + it should "decode NodeData message for all supported versions of protocol" in { + val nodeData = PV63.NodeData(Seq(exampleHash)) + val nodeDataBytes: Array[Byte] = nodeData.toBytes + + assertThrows[RuntimeException] { + decode(Codes.NodeDataCode, nodeDataBytes, ProtocolVersions.PV61) + } + assertThrows[RuntimeException] { + decode(Codes.NodeDataCode, nodeDataBytes, ProtocolVersions.PV62) + } + decode(Codes.NodeDataCode, nodeDataBytes, ProtocolVersions.PV63) shouldBe nodeData + decode(Codes.NodeDataCode, nodeDataBytes, ProtocolVersions.PV64) shouldBe nodeData + } + + it should "decode GetReceipts message for all supported versions of protocol" in { + val getReceipts = PV63.GetReceipts(Seq(exampleHash)) + val getReceiptsBytes: Array[Byte] = getReceipts.toBytes + + assertThrows[RuntimeException] { + decode(Codes.GetReceiptsCode, getReceiptsBytes, ProtocolVersions.PV61) + } + assertThrows[RuntimeException] { + decode(Codes.GetReceiptsCode, getReceiptsBytes, ProtocolVersions.PV62) + } + decode(Codes.GetReceiptsCode, getReceiptsBytes, ProtocolVersions.PV63) shouldBe getReceipts + decode(Codes.GetReceiptsCode, getReceiptsBytes, ProtocolVersions.PV64) shouldBe getReceipts + } + + it should "decode Receipts message for all supported versions of protocol" in { + val receipts = PV63.Receipts(ObjectGenerators.receiptsGen(3).sample.get) + val receiptsBytes: Array[Byte] = receipts.toBytes + + assertThrows[RuntimeException] { + decode(Codes.ReceiptsCode, receiptsBytes, ProtocolVersions.PV61) + } + assertThrows[RuntimeException] { + decode(Codes.ReceiptsCode, receiptsBytes, ProtocolVersions.PV62) + } + decode(Codes.ReceiptsCode, receiptsBytes, ProtocolVersions.PV63) shouldBe receipts + decode(Codes.ReceiptsCode, receiptsBytes, ProtocolVersions.PV64) shouldBe receipts + } + + it should "decode Status message for all supported versions of protocol" in { + val status63 = CommonMessages.Status(ProtocolVersions.PV63, 1, BigInt(100), exampleHash, exampleHash) + val status63Bytes: Array[Byte] = status63.toBytes + val status64 = PV64.Status(ProtocolVersions.PV63, 1, ChainWeight(1, BigInt(100)), exampleHash, exampleHash) + + // it's not 100 % true as Status message was different in PV61, but we are not supporting old message + decode(Codes.StatusCode, status63Bytes, ProtocolVersions.PV61) shouldBe status63 + decode(Codes.StatusCode, status63Bytes, ProtocolVersions.PV62) shouldBe status63 + decode(Codes.StatusCode, status63Bytes, ProtocolVersions.PV63) shouldBe status63 + decode(Codes.StatusCode, status64.toBytes, ProtocolVersions.PV64) shouldBe status64 + } + + it should "decode NewBlock message for all supported versions of protocol" in { + val newBlock63 = ObjectGenerators.newBlockGen(secureRandom, None).sample.get + val newBlock63Bytes: Array[Byte] = newBlock63.toBytes + val newBlock64 = ObjectGenerators.newBlock64Gen(secureRandom, None).sample.get + + decode(Codes.NewBlockCode, newBlock63Bytes, ProtocolVersions.PV61) shouldBe newBlock63 + decode(Codes.NewBlockCode, newBlock63Bytes, ProtocolVersions.PV62) shouldBe newBlock63 + decode(Codes.NewBlockCode, newBlock63Bytes, ProtocolVersions.PV63) shouldBe newBlock63 + decode(Codes.NewBlockCode, newBlock64.toBytes, ProtocolVersions.PV64) shouldBe newBlock64 + } + + it should "decode SignedTransactions message for all supported versions of protocol" in { + val signedTransactions = SignedTransactions(ObjectGenerators.signedTxSeqGen(3, secureRandom, None).sample.get) + val signedTransactionsBytes: Array[Byte] = signedTransactions.toBytes + + decode(Codes.SignedTransactionsCode, signedTransactionsBytes, ProtocolVersions.PV61) shouldBe signedTransactions + decode(Codes.SignedTransactionsCode, signedTransactionsBytes, ProtocolVersions.PV62) shouldBe signedTransactions + decode(Codes.SignedTransactionsCode, signedTransactionsBytes, ProtocolVersions.PV63) shouldBe signedTransactions + decode(Codes.SignedTransactionsCode, signedTransactionsBytes, ProtocolVersions.PV64) shouldBe signedTransactions + } + + it should "not decode message not existing in given protocol" in { + assertThrows[RuntimeException] { + decode(Codes.SignedTransactionsCode, blockHashesFromNumberBytes, ProtocolVersions.PV62) + } + } + + it should "not decode message of not supported protocol" in { + assertThrows[RuntimeException] { + decode(Codes.NewBlockHashesCode, NewBlockHashesPV61bytes, ProtocolVersions.PV61 - 1) + } + } +} diff --git a/src/test/scala/io/iohk/ethereum/network/p2p/MessageSpec.scala b/src/test/scala/io/iohk/ethereum/network/p2p/MessageSpec.scala deleted file mode 100644 index 9c56b41d55..0000000000 --- a/src/test/scala/io/iohk/ethereum/network/p2p/MessageSpec.scala +++ /dev/null @@ -1,77 +0,0 @@ -package io.iohk.ethereum.network.p2p - -import akka.util.ByteString -import io.iohk.ethereum.network.p2p.messages._ -import org.bouncycastle.util.encoders.Hex -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class MessageSpec extends AnyFlatSpec with Matchers { - - val decode = EthereumMessageDecoder.fromBytes _ - - val exampleHash = ByteString(Hex.decode("fccdbfe911f9df0a6cc0107d1240f76dfdd1d301b65fdc3cd2ae62752affbef6")) - - val NewBlockHashesPV61bytes: Array[Byte] = - Hex.decode( - "f842a0fccdbfe911f9df0a6cc0107d1240f76dfdd1d301b65fdc3cd2ae62752affbef6a0fccdbfe911f9df0a6cc0107d1240f76dfdd1d301b65fdc3cd2ae62752affbef6" - ) - val newBlockHashesPV61 = PV61.NewBlockHashes(Seq(exampleHash, exampleHash)) - - val NewBlockHashesPV62bytes: Array[Byte] = - Hex.decode( - "f846e2a0fccdbfe911f9df0a6cc0107d1240f76dfdd1d301b65fdc3cd2ae62752affbef601e2a0fccdbfe911f9df0a6cc0107d1240f76dfdd1d301b65fdc3cd2ae62752affbef602" - ) - val newBlockHashesPV62 = PV62.NewBlockHashes(Seq(PV62.BlockHash(exampleHash, 1), PV62.BlockHash(exampleHash, 2))) - - val BlockHashesFromNumberBytes: Array[Byte] = Hex.decode("c20c28") - val blockHashesFromNumber = PV61.BlockHashesFromNumber(12, 40) - - val helloBytes: Array[Byte] = - Hex.decode( - "f858048a6574632d636c69656e74c6c5836574683f820d05b840a13f3f0555b5037827c743e40fce29139fcf8c3f2a8f12753872fe906a77ff70f6a7f517be995805ff39ab73af1d53dac1a6c9786eebc5935fc455ac8f41ba67" - ) - val hello = WireProtocol.Hello( - p2pVersion = 4, - /** TODO change the expected bytyes to reflect the name change from etc-cleint to mantis * */ - clientId = "etc-client", - capabilities = Seq(WireProtocol.Capability("eth", Versions.PV63.toByte)), - listenPort = 3333, - nodeId = ByteString( - Hex.decode( - "a13f3f0555b5037827c743e40fce29139fcf8c3f2a8f12753872fe906a77ff70f6a7f517be995805ff39ab73af1d53dac1a6c9786eebc5935fc455ac8f41ba67" - ) - ) - ) - - "Message" should "decode message from given version of protocol" in { - decode(PV61.NewBlockHashes.code, NewBlockHashesPV61bytes, Versions.PV61) shouldBe newBlockHashesPV61 - } - - it should "decode message redefined in newer version of protocol" in { - decode(PV62.NewBlockHashes.code, NewBlockHashesPV62bytes, Versions.PV62) shouldBe newBlockHashesPV62 - decode(PV62.NewBlockHashes.code, NewBlockHashesPV62bytes, Versions.PV63) shouldBe newBlockHashesPV62 - } - - it should "decode message available only in older version of protocol" in { - decode(PV61.BlockHashesFromNumber.code, BlockHashesFromNumberBytes, Versions.PV61) shouldBe blockHashesFromNumber - } - - it should "not decode message from older version of protocol as newer version" in { - assertThrows[RuntimeException] { - decode(PV62.NewBlockHashes.code, NewBlockHashesPV61bytes, Versions.PV62) - } - } - - it should "not decode message not existing in given protocol" in { - assertThrows[RuntimeException] { - decode(CommonMessages.SignedTransactions.code, BlockHashesFromNumberBytes, Versions.PV62) - } - } - - it should "decode wire protocol message for all versions of protocol" in { - decode(WireProtocol.Hello.code, helloBytes, Versions.PV61) shouldBe hello - decode(WireProtocol.Hello.code, helloBytes, Versions.PV62) shouldBe hello - decode(WireProtocol.Hello.code, helloBytes, Versions.PV63) shouldBe hello - } -} diff --git a/src/test/scala/io/iohk/ethereum/network/p2p/PeerActorSpec.scala b/src/test/scala/io/iohk/ethereum/network/p2p/PeerActorSpec.scala index cde6be0c34..c0e29a0e47 100644 --- a/src/test/scala/io/iohk/ethereum/network/p2p/PeerActorSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/p2p/PeerActorSpec.scala @@ -8,19 +8,23 @@ import akka.actor.{ActorSystem, PoisonPill, Props, Terminated} import akka.testkit.{TestActorRef, TestKit, TestProbe} import akka.util.ByteString import com.miguno.akka.testing.VirtualTime +import io.iohk.ethereum._ import io.iohk.ethereum.blockchain.sync.EphemBlockchainTestSetup import io.iohk.ethereum.crypto.generateKeyPair import io.iohk.ethereum.db.storage.AppStateStorage import io.iohk.ethereum.domain._ +import io.iohk.ethereum.network.EtcPeerManagerActor.RemoteStatus import io.iohk.ethereum.network.PeerActor.Status.Handshaked import io.iohk.ethereum.network.PeerActor.{GetStatus, StatusResponse} import io.iohk.ethereum.network.PeerManagerActor.{FastSyncHostConfiguration, PeerConfiguration} import io.iohk.ethereum.network.handshaker.{EtcHandshaker, EtcHandshakerConfiguration} +import io.iohk.ethereum.network.p2p.Message.Version +import io.iohk.ethereum.network.p2p.messages.Capability.Capabilities._ import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status import io.iohk.ethereum.network.p2p.messages.CommonMessages.Status.StatusEnc import io.iohk.ethereum.network.p2p.messages.PV62.GetBlockHeaders.GetBlockHeadersEnc import io.iohk.ethereum.network.p2p.messages.PV62._ -import io.iohk.ethereum.network.p2p.messages.Versions +import io.iohk.ethereum.network.p2p.messages.{PV64, ProtocolVersions} import io.iohk.ethereum.network.p2p.messages.WireProtocol.Disconnect.Reasons import io.iohk.ethereum.network.p2p.messages.WireProtocol.Hello.HelloEnc import io.iohk.ethereum.network.p2p.messages.WireProtocol.Pong.PongEnc @@ -29,8 +33,7 @@ import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler.RLPxConfiguration import io.iohk.ethereum.network.{ForkResolver, PeerActor, PeerEventBusActor, _} import io.iohk.ethereum.nodebuilder.SecureRandomBuilder -import io.iohk.ethereum.utils.{BlockchainConfig, Config, NodeStatus, ServerStatus} -import io.iohk.ethereum.{Fixtures, Mocks, Timeouts, WithActorSystemShutDown, crypto} +import io.iohk.ethereum.utils.{Config, NodeStatus, ServerStatus} import org.bouncycastle.crypto.AsymmetricCipherKeyPair import org.bouncycastle.crypto.params.ECPublicKeyParameters import org.bouncycastle.util.encoders.Hex @@ -78,6 +81,7 @@ class PeerActorSpec it should "try to reconnect on broken rlpx connection" in new NodeStatusSetup with HandshakerSetup { override implicit lazy val system = ActorSystem("PeerActorSpec_System") + override def protocol: Version = ProtocolVersions.PV63 val time = new VirtualTime @@ -128,14 +132,14 @@ class PeerActorSpec rlpxConnection.reply(RLPxConnectionHandler.ConnectionEstablished(remoteNodeId)) //Hello exchange - val remoteHello = Hello(4, "test-client", Seq(Capability("eth", Versions.PV63.toByte)), 9000, ByteString("unused")) + val remoteHello = Hello(4, "test-client", Seq(Eth63Capability), 9000, ByteString("unused")) rlpxConnection.expectMsgPF() { case RLPxConnectionHandler.SendMessage(_: HelloEnc) => () } rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(remoteHello)) val remoteStatus = Status( - protocolVersion = Versions.PV63, + protocolVersion = ProtocolVersions.PV63, networkId = peerConf.networkId, - chainWeight = daoForkBlockChainWeight.increaseTotalDifficulty(100000), // remote is after the fork + totalDifficulty = daoForkBlockChainTotalDifficulty + 100000, // remote is after the fork bestHash = ByteString("blockhash"), genesisHash = genesisHash ) @@ -156,6 +160,45 @@ class PeerActorSpec knownNodesManager.expectNoMessage() } + it should "successfully connect to ETC peer with protocol 64" in new TestSetup { + override def protocol: Version = ProtocolVersions.PV64 + val uri = new URI(s"enode://${Hex.toHexString(remoteNodeId.toArray[Byte])}@localhost:9000") + val completeUri = new URI(s"enode://${Hex.toHexString(remoteNodeId.toArray[Byte])}@127.0.0.1:9000?discport=9000") + peer ! PeerActor.ConnectTo(uri) + peer ! PeerActor.ConnectTo(uri) + + rlpxConnection.expectMsgClass(classOf[RLPxConnectionHandler.ConnectTo]) + rlpxConnection.reply(RLPxConnectionHandler.ConnectionEstablished(remoteNodeId)) + + //Hello exchange + val remoteHello = Hello(4, "test-client", Seq(Etc64Capability, Eth63Capability), 9000, ByteString("unused")) + rlpxConnection.expectMsgPF() { case RLPxConnectionHandler.SendMessage(_: HelloEnc) => () } + rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(remoteHello)) + + val remoteStatus = PV64.Status( + protocolVersion = ProtocolVersions.PV64, + networkId = peerConf.networkId, + chainWeight = ChainWeight.totalDifficultyOnly(daoForkBlockChainTotalDifficulty + 100000), // remote is after the fork + bestHash = ByteString("blockhash"), + genesisHash = genesisHash + ) + + //Node status exchange + rlpxConnection.expectMsgPF() { case RLPxConnectionHandler.SendMessage(_: PV64.Status.StatusEnc) => () } + rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(remoteStatus)) + + //Fork block exchange + rlpxConnection.expectMsgPF() { case RLPxConnectionHandler.SendMessage(_: GetBlockHeadersEnc) => () } + rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(BlockHeaders(Seq(etcForkBlockHeader)))) + + //Check that peer is connected + rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(Ping())) + rlpxConnection.expectMsg(RLPxConnectionHandler.SendMessage(Pong())) + + knownNodesManager.expectMsg(KnownNodesManager.AddKnownNode(completeUri)) + knownNodesManager.expectNoMessage() + } + it should "successfully connect to and IPv6 peer" in new TestSetup { val uri = new URI(s"enode://${Hex.toHexString(remoteNodeId.toArray[Byte])}@[::]:9000") val completeUri = @@ -166,14 +209,14 @@ class PeerActorSpec rlpxConnection.reply(RLPxConnectionHandler.ConnectionEstablished(remoteNodeId)) //Hello exchange - val remoteHello = Hello(4, "test-client", Seq(Capability("eth", Versions.PV63.toByte)), 9000, ByteString("unused")) + val remoteHello = Hello(4, "test-client", Seq(Eth63Capability), 9000, ByteString("unused")) rlpxConnection.expectMsgPF() { case RLPxConnectionHandler.SendMessage(_: HelloEnc) => () } rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(remoteHello)) val remoteStatus = Status( - protocolVersion = Versions.PV63, + protocolVersion = ProtocolVersions.PV63, networkId = peerConf.networkId, - chainWeight = daoForkBlockChainWeight.increaseTotalDifficulty(100000), // remote is after the fork + totalDifficulty = daoForkBlockChainTotalDifficulty + 100000, // remote is after the fork bestHash = ByteString("blockhash"), genesisHash = genesisHash ) @@ -200,13 +243,13 @@ class PeerActorSpec rlpxConnection.expectMsgClass(classOf[RLPxConnectionHandler.ConnectTo]) rlpxConnection.reply(RLPxConnectionHandler.ConnectionEstablished(remoteNodeId)) - val remoteHello = Hello(4, "test-client", Seq(Capability("eth", Versions.PV63.toByte)), 9000, ByteString("unused")) + val remoteHello = Hello(4, "test-client", Seq(Eth63Capability), 9000, ByteString("unused")) rlpxConnection.expectMsgPF() { case RLPxConnectionHandler.SendMessage(_: HelloEnc) => () } rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(remoteHello)) val header = Fixtures.Blocks.ValidBlock.header - .copy(difficulty = daoForkBlockChainWeight.totalDifficulty + 100000, number = 3000000) + .copy(difficulty = daoForkBlockChainTotalDifficulty + 100000, number = 3000000) storagesInstance.storages.appStateStorage .putBestBlockNumber(3000000) // after the fork .and(blockchain.storeBlockHeader(header)) @@ -214,9 +257,9 @@ class PeerActorSpec .commit() val remoteStatus = Status( - protocolVersion = Versions.PV63, + protocolVersion = ProtocolVersions.PV63, networkId = peerConf.networkId, - chainWeight = daoForkBlockChainWeight.increaseTotalDifficulty(100000), // remote is after the fork + totalDifficulty = daoForkBlockChainTotalDifficulty + 100000, // remote is after the fork bestHash = ByteString("blockhash"), genesisHash = genesisHash ) @@ -235,14 +278,14 @@ class PeerActorSpec rlpxConnection.expectMsgClass(classOf[RLPxConnectionHandler.ConnectTo]) rlpxConnection.reply(RLPxConnectionHandler.ConnectionEstablished(remoteNodeId)) - val remoteHello = Hello(4, "test-client", Seq(Capability("eth", Versions.PV63.toByte)), 9000, ByteString("unused")) + val remoteHello = Hello(4, "test-client", Seq(Eth63Capability), 9000, ByteString("unused")) rlpxConnection.expectMsgPF() { case RLPxConnectionHandler.SendMessage(_: HelloEnc) => () } rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(remoteHello)) val remoteStatus = Status( - protocolVersion = Versions.PV63, + protocolVersion = ProtocolVersions.PV63, networkId = peerConf.networkId, - chainWeight = daoForkBlockChainWeight.increaseTotalDifficulty(100000), // remote is after the fork + totalDifficulty = daoForkBlockChainTotalDifficulty + 100000, // remote is after the fork bestHash = ByteString("blockhash"), genesisHash = genesisHash ) @@ -282,14 +325,14 @@ class PeerActorSpec rlpxConnection.expectMsgClass(classOf[RLPxConnectionHandler.ConnectTo]) rlpxConnection.reply(RLPxConnectionHandler.ConnectionEstablished(remoteNodeId)) - val remoteHello = Hello(4, "test-client", Seq(Capability("eth", Versions.PV63.toByte)), 9000, ByteString("unused")) + val remoteHello = Hello(4, "test-client", Seq(Eth63Capability), 9000, ByteString("unused")) rlpxConnection.expectMsgPF() { case RLPxConnectionHandler.SendMessage(_: HelloEnc) => () } rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(remoteHello)) val remoteStatus = Status( - protocolVersion = Versions.PV63, + protocolVersion = ProtocolVersions.PV63, networkId = peerConf.networkId, - chainWeight = daoForkBlockChainWeight.increaseTotalDifficulty(100000), // remote is after the fork + totalDifficulty = daoForkBlockChainTotalDifficulty + 100000, // remote is after the fork bestHash = ByteString("blockhash"), genesisHash = genesisHash ) @@ -314,14 +357,14 @@ class PeerActorSpec rlpxConnection.expectMsgClass(classOf[RLPxConnectionHandler.ConnectTo]) rlpxConnection.reply(RLPxConnectionHandler.ConnectionEstablished(remoteNodeId)) - val remoteHello = Hello(4, "test-client", Seq(Capability("eth", Versions.PV63.toByte)), 9000, ByteString("unused")) + val remoteHello = Hello(4, "test-client", Seq(Eth63Capability), 9000, ByteString("unused")) rlpxConnection.expectMsgPF() { case RLPxConnectionHandler.SendMessage(_: HelloEnc) => () } rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(remoteHello)) val remoteStatus = Status( - protocolVersion = Versions.PV63, + protocolVersion = ProtocolVersions.PV63, networkId = peerConf.networkId, - chainWeight = daoForkBlockChainWeight.increaseTotalDifficulty(100000), // remote is after the fork + totalDifficulty = daoForkBlockChainTotalDifficulty + 100000, // remote is after the fork bestHash = ByteString("blockhash"), genesisHash = genesisHash ) @@ -337,10 +380,10 @@ class PeerActorSpec it should "stay connected to pre fork peer" in new TestSetup { - val remoteStatus = Status( - protocolVersion = Versions.PV63, + val remoteStatus = RemoteStatus( + protocolVersion = ProtocolVersions.PV63, networkId = peerConf.networkId, - chainWeight = daoForkBlockChainWeight.increaseTotalDifficulty(-200000), // remote is before the fork + chainWeight = ChainWeight.totalDifficultyOnly(daoForkBlockChainTotalDifficulty - 200000), // remote is before the fork bestHash = ByteString("blockhash"), genesisHash = Fixtures.Blocks.Genesis.header.hash ) @@ -375,14 +418,14 @@ class PeerActorSpec rlpxConnection.expectMsgClass(classOf[RLPxConnectionHandler.ConnectTo]) rlpxConnection.reply(RLPxConnectionHandler.ConnectionEstablished(remoteNodeId)) - val remoteHello = Hello(4, "test-client", Seq(Capability("eth", Versions.PV63.toByte)), 9000, ByteString("unused")) + val remoteHello = Hello(4, "test-client", Seq(Eth63Capability), 9000, ByteString("unused")) rlpxConnection.expectMsgPF() { case RLPxConnectionHandler.SendMessage(_: HelloEnc) => () } rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(remoteHello)) val remoteStatus = Status( - protocolVersion = Versions.PV63, + protocolVersion = ProtocolVersions.PV63, networkId = peerConf.networkId, - chainWeight = daoForkBlockChainWeight.increaseTotalDifficulty(100000), // remote is after the fork + totalDifficulty = daoForkBlockChainTotalDifficulty + 100000, // remote is after the fork bestHash = ByteString("blockhash"), genesisHash = genesisHash ) @@ -477,6 +520,8 @@ class PeerActorSpec } trait HandshakerSetup extends NodeStatusSetup { self => + def protocol: Version + val handshakerConfiguration = new EtcHandshakerConfiguration { override val forkResolverOpt: Option[ForkResolver] = Some( new ForkResolver.EtcForkResolver(self.blockchainConfig.daoForkConfig.get) @@ -484,48 +529,19 @@ class PeerActorSpec override val nodeStatusHolder: AtomicReference[NodeStatus] = self.nodeStatusHolder override val peerConfiguration: PeerConfiguration = self.peerConf override val blockchain: Blockchain = self.blockchain - override val blockchainConfig: BlockchainConfig = self.blockchainConfig override val appStateStorage: AppStateStorage = self.storagesInstance.storages.appStateStorage + override val protocolVersion: Int = protocol } val handshaker = EtcHandshaker(handshakerConfiguration) } trait TestSetup extends NodeStatusSetup with BlockUtils with HandshakerSetup { + override def protocol: Version = ProtocolVersions.PV63 val genesisHash = genesisBlock.hash - val daoForkBlockChainWeight = ChainWeight.totalDifficultyOnly(BigInt("39490964433395682584")) - - def setupConnection(): Unit = { - peer ! PeerActor.ConnectTo(new URI("encode://localhost:9000")) - - rlpxConnection.expectMsgClass(classOf[RLPxConnectionHandler.ConnectTo]) - rlpxConnection.reply(RLPxConnectionHandler.ConnectionEstablished(remoteNodeId)) - - val remoteHello = - Hello(4, "test-client", Seq(Capability("eth", Versions.PV63.toByte)), 9000, ByteString("unused")) - rlpxConnection.expectMsgPF() { case RLPxConnectionHandler.SendMessage(_: HelloEnc) => () } - rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(remoteHello)) - - val remoteStatus = Status( - protocolVersion = Versions.PV63, - networkId = peerConf.networkId, - chainWeight = daoForkBlockChainWeight.increaseTotalDifficulty(100000), // remote is after the fork - bestHash = ByteString("blockhash"), - genesisHash = genesisHash - ) - - rlpxConnection.expectMsgPF() { case RLPxConnectionHandler.SendMessage(_: StatusEnc) => () } - rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(remoteStatus)) - - rlpxConnection.expectMsgPF() { case RLPxConnectionHandler.SendMessage(_: GetBlockHeadersEnc) => () } - rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(BlockHeaders(Seq(etcForkBlockHeader)))) - - // ask for highest block - rlpxConnection.expectMsgPF() { case RLPxConnectionHandler.SendMessage(_: GetBlockHeadersEnc) => () } - rlpxConnection.send(peer, RLPxConnectionHandler.MessageReceived(BlockHeaders(Nil))) - } + val daoForkBlockChainTotalDifficulty = BigInt("39490964433395682584") val rlpxConnection = TestProbe() diff --git a/src/test/scala/io/iohk/ethereum/network/p2p/messages/MessagesSerializationSpec.scala b/src/test/scala/io/iohk/ethereum/network/p2p/messages/MessagesSerializationSpec.scala index 7533deaef5..44983f0b1f 100644 --- a/src/test/scala/io/iohk/ethereum/network/p2p/messages/MessagesSerializationSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/p2p/messages/MessagesSerializationSpec.scala @@ -14,6 +14,7 @@ import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks class MessagesSerializationSpec extends AnyWordSpec with ScalaCheckPropertyChecks with Matchers { + // TODO: add tests for messages from PV63 "Wire Protocol" when { "encoding and decoding Hello" should { @@ -22,7 +23,7 @@ class MessagesSerializationSpec extends AnyWordSpec with ScalaCheckPropertyCheck Hello(1, "teest", Seq(Capability("Sample", 1), Capability("Sample", 2)), 1, ByteString("Id")), (m: Hello) => m.toBytes, Hello.code, - Versions.PV63 + ProtocolVersions.PV63 ) } } @@ -33,20 +34,20 @@ class MessagesSerializationSpec extends AnyWordSpec with ScalaCheckPropertyCheck Disconnect(Disconnect.Reasons.AlreadyConnected), (m: Disconnect) => m.toBytes, Disconnect.code, - Versions.PV63 + ProtocolVersions.PV63 ) } } "encoding and decoding Ping" should { "return same result" in { - verify(Ping(), (m: Ping) => m.toBytes, Ping.code, Versions.PV63) + verify(Ping(), (m: Ping) => m.toBytes, Ping.code, ProtocolVersions.PV63) } } "encoding and decoding Pong" should { "return same result" in { - verify(Pong(), (m: Pong) => m.toBytes, Pong.code, Versions.PV63) + verify(Pong(), (m: Pong) => m.toBytes, Pong.code, ProtocolVersions.PV63) } } } @@ -54,90 +55,96 @@ class MessagesSerializationSpec extends AnyWordSpec with ScalaCheckPropertyCheck "Common Messages" when { "encoding and decoding Status" should { "return same result for Status v63" in { - val msg = Status(1, 2, ChainWeight.totalDifficultyOnly(2), ByteString("HASH"), ByteString("HASH2")).as63 - verify(msg, (m: Status) => m.toBytes, Status.code63, Versions.PV63) - } - - "return same result for Status v64" in { - val msg = Status(1, 2, ChainWeight(2, 5), ByteString("HASH"), ByteString("HASH2")).as64 - verify(msg, (m: Status) => m.toBytes, Status.code64, Versions.PV63) + val msg = Status(1, 2, 2, ByteString("HASH"), ByteString("HASH2")) + verify(msg, (m: Status) => m.toBytes, Codes.StatusCode, ProtocolVersions.PV63) } } "encoding and decoding SignedTransactions" should { "return same result" in { val msg = SignedTransactions(Fixtures.Blocks.Block3125369.body.transactionList) - verify(msg, (m: SignedTransactions) => m.toBytes, SignedTransactions.code, Versions.PV63) + verify(msg, (m: SignedTransactions) => m.toBytes, Codes.SignedTransactionsCode, ProtocolVersions.PV63) } } "encoding and decoding NewBlock" should { "return same result for NewBlock v63" in { - val msg = NewBlock(Fixtures.Blocks.Block3125369.block, ChainWeight.totalDifficultyOnly(2323)).as63 - verify(msg, (m: NewBlock) => m.toBytes, NewBlock.code63, Versions.PV63) + val msg = NewBlock(Fixtures.Blocks.Block3125369.block, 2323) + verify(msg, (m: NewBlock) => m.toBytes, Codes.NewBlockCode, ProtocolVersions.PV63) } + } + } + "PV64" when { + "encoding and decoding Status" should { + "return same result for Status v64" in { + val msg = PV64.Status(1, 2, ChainWeight(2, 5), ByteString("HASH"), ByteString("HASH2")) + verify(msg, (m: PV64.Status) => m.toBytes, Codes.StatusCode, ProtocolVersions.PV64) + } + } + + "encoding and decoding NewBlock" should { "return same result for NewBlock v64" in { - val msg = NewBlock(Fixtures.Blocks.Block3125369.block, ChainWeight(2323, 21)).as64 - verify(msg, (m: NewBlock) => m.toBytes, NewBlock.code64, Versions.PV63) + val msg = PV64.NewBlock(Fixtures.Blocks.Block3125369.block, ChainWeight(2323, 21)) + verify(msg, (m: PV64.NewBlock) => m.toBytes, Codes.NewBlockCode, ProtocolVersions.PV64) } } } "PV61" when { - val version = Versions.PV61 + val version = ProtocolVersions.PV61 "encoding and decoding NewBlockHashes" should { "return same result" in { val msg = PV61.NewBlockHashes(Seq(ByteString("23"), ByteString("10"), ByteString("36"))) - verify(msg, (m: PV61.NewBlockHashes) => m.toBytes, PV61.NewBlockHashes.code, version) + verify(msg, (m: PV61.NewBlockHashes) => m.toBytes, Codes.NewBlockHashesCode, version) } } "encoding and decoding BlockHashesFromNumber" should { "return same result" in { val msg = BlockHashesFromNumber(1, 2) - verify(msg, (m: BlockHashesFromNumber) => m.toBytes, BlockHashesFromNumber.code, version) + verify(msg, (m: BlockHashesFromNumber) => m.toBytes, Codes.BlockHashesFromNumberCode, version) } } } "PV62" when { - val version = Versions.PV62 + val version = ProtocolVersions.PV62 "encoding and decoding NewBlockHashes" should { "return same result" in { val msg = PV62.NewBlockHashes(Seq(BlockHash(ByteString("hash1"), 1), BlockHash(ByteString("hash2"), 2))) - verify(msg, (m: PV62.NewBlockHashes) => m.toBytes, PV62.NewBlockHashes.code, version) + verify(msg, (m: PV62.NewBlockHashes) => m.toBytes, Codes.NewBlockHashesCode, version) } } "encoding and decoding BlockBodies" should { "return same result" in { val msg = BlockBodies(Seq(Fixtures.Blocks.Block3125369.body, Fixtures.Blocks.DaoForkBlock.body)) - verify(msg, (m: BlockBodies) => m.toBytes, BlockBodies.code, version) + verify(msg, (m: BlockBodies) => m.toBytes, Codes.BlockBodiesCode, version) } } "encoding and decoding GetBlockBodies" should { "return same result" in { val msg = GetBlockBodies(Seq(ByteString("111"), ByteString("2222"))) - verify(msg, (m: GetBlockBodies) => m.toBytes, GetBlockBodies.code, version) + verify(msg, (m: GetBlockBodies) => m.toBytes, Codes.GetBlockBodiesCode, version) } } "encoding and decoding BlockHeaders" should { "return same result" in { val msg = BlockHeaders(Seq(Fixtures.Blocks.Block3125369.header, Fixtures.Blocks.DaoForkBlock.header)) - verify(msg, (m: BlockHeaders) => m.toBytes, BlockHeaders.code, version) + verify(msg, (m: BlockHeaders) => m.toBytes, Codes.BlockHeadersCode, version) } } "encoding and decoding GetBlockHeaders" should { "return same result" in { - verify(GetBlockHeaders(Left(1), 1, 1, false), (m: GetBlockHeaders) => m.toBytes, GetBlockHeaders.code, version) + verify(GetBlockHeaders(Left(1), 1, 1, false), (m: GetBlockHeaders) => m.toBytes, Codes.GetBlockHeadersCode, version) verify( GetBlockHeaders(Right(ByteString("1" * 32)), 1, 1, true), (m: GetBlockHeaders) => m.toBytes, - GetBlockHeaders.code, + Codes.GetBlockHeadersCode, version ) } diff --git a/src/test/scala/io/iohk/ethereum/network/p2p/messages/NewBlockSpec.scala b/src/test/scala/io/iohk/ethereum/network/p2p/messages/NewBlockSpec.scala index d5446826d3..724c7049f9 100644 --- a/src/test/scala/io/iohk/ethereum/network/p2p/messages/NewBlockSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/p2p/messages/NewBlockSpec.scala @@ -15,34 +15,32 @@ class NewBlockSpec extends AnyFunSuite with ScalaCheckPropertyChecks with Object val chainId = Hex.decode("3d").head test("NewBlock v63 messages are encoded and decoded properly") { - forAll(newBlockGen(secureRandom, Some(chainId)).map(_.as63)) { newBlock => + forAll(newBlockGen(secureRandom, Some(chainId))) { newBlock => val encoded: Array[Byte] = newBlock.toBytes - val decoded: NewBlock = encoded.toNewBlock(NewBlock.code63) - val newBlockWithoutCheckpointNumber = - newBlock.copy(chainWeight = ChainWeight.totalDifficultyOnly(newBlock.chainWeight.totalDifficulty)) - assert(decoded == newBlockWithoutCheckpointNumber) + val decoded: NewBlock = encoded.toNewBlock + assert(decoded == newBlock) } } test("NewBlock v64 messages are encoded and decoded properly") { - forAll(newBlockGen(secureRandom, Some(chainId)).map(_.as64)) { newBlock => + import io.iohk.ethereum.network.p2p.messages.PV64.NewBlock._ + forAll(newBlock64Gen(secureRandom, Some(chainId))) { newBlock => val encoded: Array[Byte] = newBlock.toBytes - val decoded: NewBlock = encoded.toNewBlock(NewBlock.code64) + val decoded: PV64.NewBlock = encoded.toNewBlock assert(decoded == newBlock) } } - //Expected encoded NewBlock obtained from EthereumJ test("NewBlock messages are properly encoded") { - val obtainEncoded = Hex.toHexString(newBlock.as63.toBytes) + val obtainEncoded = Hex.toHexString(newBlock.toBytes) val expectedEncoded = "f90200f901f9f901f4a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347943333333333333333333333333333333333333333a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830f0000808408000000808000a0000000000000000000000000000000000000000000000000000000000000000088deadbeefdeadbeefc0c0830f0000" assert(obtainEncoded == expectedEncoded) - val obtainEncoded2 = Hex.toHexString(newBlock2.as63.toBytes) - val expectedEncoded2 = - "f9021cf90215f90210a098352d9c1300bd82334cb3e5034c3ec622d437963f55cf5a00a49642806c2f32a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942cad6e80c7c0b58845fcd71ecad6867c3bd4de20a09b56d589ad6a12373e212fdb6cb4f64d1d7745aea551c7116c665a81a31f9492a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830f0b3f0a8407ec167f808458a6eb7098d783010507846765746887676f312e372e33856c696e7578a0ea0dec34a635401af44f5245a77b2cd838345615c555c322a3001df4dd0505fe8860d53a11c10d46fbc0c0830f0b3f" - assert(obtainEncoded2 == expectedEncoded2) + val obtainEncoded64 = Hex.toHexString(newBlock64.toBytes) + val expectedEncoded64 = + "f9021df90215f90210a098352d9c1300bd82334cb3e5034c3ec622d437963f55cf5a00a49642806c2f32a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942cad6e80c7c0b58845fcd71ecad6867c3bd4de20a09b56d589ad6a12373e212fdb6cb4f64d1d7745aea551c7116c665a81a31f9492a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830f0b3f0a8407ec167f808458a6eb7098d783010507846765746887676f312e372e33856c696e7578a0ea0dec34a635401af44f5245a77b2cd838345615c555c322a3001df4dd0505fe8860d53a11c10d46fbc0c0830f0b3f04" + assert(obtainEncoded64 == expectedEncoded64) } val newBlock = NewBlock( @@ -66,10 +64,10 @@ class NewBlockSpec extends AnyFunSuite with ScalaCheckPropertyChecks with Object ), BlockBody(Seq(), Seq()) ), - ChainWeight.totalDifficultyOnly(983040) + 983040 ) - val newBlock2 = NewBlock( + val newBlock64 = PV64.NewBlock( Block( BlockHeader( parentHash = ByteString(Hex.decode("98352d9c1300bd82334cb3e5034c3ec622d437963f55cf5a00a49642806c2f32")), diff --git a/src/test/scala/io/iohk/ethereum/network/p2p/messages/NodeDataSpec.scala b/src/test/scala/io/iohk/ethereum/network/p2p/messages/NodeDataSpec.scala index 1a2762440a..392bfa153d 100644 --- a/src/test/scala/io/iohk/ethereum/network/p2p/messages/NodeDataSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/p2p/messages/NodeDataSpec.scala @@ -75,7 +75,7 @@ class NodeDataSpec extends AnyFlatSpec with Matchers { } it should "be decoded properly" in { - val result = EthereumMessageDecoder.fromBytes(NodeData.code, encode(encodedNodeData), Versions.PV63) + val result = EthereumMessageDecoder.fromBytes(Codes.NodeDataCode, encode(encodedNodeData), ProtocolVersions.PV63) result match { case m: NodeData => @@ -89,7 +89,7 @@ class NodeDataSpec extends AnyFlatSpec with Matchers { } it should "be decoded previously encoded value" in { - EthereumMessageDecoder.fromBytes(NodeData.code, nodeData.toBytes, Versions.PV63) shouldBe nodeData + EthereumMessageDecoder.fromBytes(Codes.NodeDataCode, nodeData.toBytes, ProtocolVersions.PV63) shouldBe nodeData } it should "decode branch node with values in leafs that looks like RLP list" in { diff --git a/src/test/scala/io/iohk/ethereum/network/p2p/messages/ReceiptsSpec.scala b/src/test/scala/io/iohk/ethereum/network/p2p/messages/ReceiptsSpec.scala index be306ece4e..83f3045170 100644 --- a/src/test/scala/io/iohk/ethereum/network/p2p/messages/ReceiptsSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/p2p/messages/ReceiptsSpec.scala @@ -51,10 +51,10 @@ class ReceiptsSpec extends AnyFlatSpec with Matchers { } it should "decode receipts" in { - EthereumMessageDecoder.fromBytes(Receipts.code, encode(encodedReceipts), Versions.PV63) shouldBe receipts + EthereumMessageDecoder.fromBytes(Codes.ReceiptsCode, encode(encodedReceipts), ProtocolVersions.PV63) shouldBe receipts } it should "decode encoded receipts" in { - EthereumMessageDecoder.fromBytes(Receipts.code, receipts.toBytes, Versions.PV63) shouldBe receipts + EthereumMessageDecoder.fromBytes(Codes.ReceiptsCode, receipts.toBytes, ProtocolVersions.PV63) shouldBe receipts } } diff --git a/src/test/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandlerSpec.scala b/src/test/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandlerSpec.scala index 3506a2299d..856e64bd55 100644 --- a/src/test/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandlerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandlerSpec.scala @@ -9,7 +9,7 @@ import akka.util.ByteString import io.iohk.ethereum.{Timeouts, WithActorSystemShutDown} import io.iohk.ethereum.network.p2p.Message.Version import io.iohk.ethereum.network.p2p.{MessageDecoder, MessageSerializable} -import io.iohk.ethereum.network.p2p.messages.Versions +import io.iohk.ethereum.network.p2p.messages.ProtocolVersions import io.iohk.ethereum.network.p2p.messages.WireProtocol.Ping import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler.RLPxConfiguration import io.iohk.ethereum.nodebuilder.SecureRandomBuilder @@ -177,7 +177,7 @@ class RLPxConnectionHandlerSpec override def fromBytes(`type`: Int, payload: Array[Byte], protocolVersion: Version) = throw new Exception("Mock message decoder fails to decode all messages") } - val protocolVersion = Versions.PV63 + val protocolVersion = ProtocolVersions.PV63 val mockHandshaker = mock[AuthHandshaker] val connection = TestProbe() val mockMessageCodec = mock[MessageCodec]