Skip to content

Commit 8780e8c

Browse files
[ETCM-355] Introduce ETH64 message format
1 parent 6b0ce37 commit 8780e8c

File tree

4 files changed

+126
-8
lines changed

4 files changed

+126
-8
lines changed

src/main/scala/io/iohk/ethereum/network/p2p/MessageDecoders.scala

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,30 @@ object ETC64MessageDecoder extends MessageDecoder {
5555
}
5656
}
5757

58+
object ETH64MessageDecoder extends MessageDecoder {
59+
import io.iohk.ethereum.network.p2p.messages.ETH64.Status._
60+
import io.iohk.ethereum.network.p2p.messages.BaseETH6XMessages.NewBlock._
61+
62+
def fromBytes(msgCode: Int, payload: Array[Byte]): Message = {
63+
msgCode match {
64+
case Codes.GetNodeDataCode => payload.toGetNodeData
65+
case Codes.NodeDataCode => payload.toNodeData
66+
case Codes.GetReceiptsCode => payload.toGetReceipts
67+
case Codes.ReceiptsCode => payload.toReceipts
68+
case Codes.NewBlockHashesCode => payload.toNewBlockHashes
69+
case Codes.GetBlockHeadersCode => payload.toGetBlockHeaders
70+
case Codes.BlockHeadersCode => payload.toBlockHeaders
71+
case Codes.GetBlockBodiesCode => payload.toGetBlockBodies
72+
case Codes.BlockBodiesCode => payload.toBlockBodies
73+
case Codes.BlockHashesFromNumberCode => payload.toBlockHashesFromNumber
74+
case Codes.StatusCode => payload.toStatus
75+
case Codes.NewBlockCode => payload.toNewBlock
76+
case Codes.SignedTransactionsCode => payload.toSignedTransactions
77+
case _ => throw new RuntimeException(s"Unknown message type: $msgCode")
78+
}
79+
}
80+
}
81+
5882
object ETH63MessageDecoder extends MessageDecoder {
5983
import io.iohk.ethereum.network.p2p.messages.BaseETH6XMessages.Status._
6084
import io.iohk.ethereum.network.p2p.messages.BaseETH6XMessages.NewBlock._
@@ -85,6 +109,7 @@ object EthereumMessageDecoder {
85109
protocolVersion match {
86110
case Capability.Capabilities.Etc64Capability => ETC64MessageDecoder.fromBytes
87111
case Capability.Capabilities.Eth63Capability => ETH63MessageDecoder.fromBytes
112+
case Capability.Capabilities.Eth64Capability => ETH64MessageDecoder.fromBytes
88113
case _ => throw new RuntimeException(s"Unsupported Protocol Version $protocolVersion")
89114
}
90115
}

src/main/scala/io/iohk/ethereum/network/p2p/messages/Capability.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ object Capability {
5151

5252
object Capabilities {
5353
val Eth63Capability: Capability = ProtocolVersions.ETH63
54+
val Eth64Capability: Capability = ProtocolVersions.ETH64
5455
val Etc64Capability: Capability = ProtocolVersions.ETC64
5556

56-
val All: Seq[Capability] = Seq(ProtocolVersions.ETC64, ProtocolVersions.ETH63)
57+
val All: Seq[Capability] = Seq(ProtocolVersions.ETC64, ProtocolVersions.ETH63, ProtocolVersions.ETH64)
5758
}
5859
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package io.iohk.ethereum.network.p2p.messages
2+
3+
import akka.util.ByteString
4+
import io.iohk.ethereum.domain._
5+
import io.iohk.ethereum.forkid.ForkId
6+
import io.iohk.ethereum.forkid.ForkId._
7+
import io.iohk.ethereum.mpt.{MptNode, MptTraversals}
8+
import io.iohk.ethereum.network.p2p.{Message, MessageSerializableImplicit}
9+
import io.iohk.ethereum.rlp.RLPImplicitConversions._
10+
import io.iohk.ethereum.rlp.RLPImplicits._
11+
import io.iohk.ethereum.rlp._
12+
import org.bouncycastle.util.encoders.Hex
13+
14+
object ETH64 {
15+
16+
case class Status(
17+
protocolVersion: Int,
18+
networkId: Int,
19+
totalDifficulty: BigInt,
20+
bestHash: ByteString,
21+
genesisHash: ByteString,
22+
forkId: ForkId
23+
) extends Message {
24+
25+
override def toString: String =
26+
s"Status { " +
27+
s"code: $code, " +
28+
s"protocolVersion: $protocolVersion, " +
29+
s"networkId: $networkId, " +
30+
s"totalDifficulty: $totalDifficulty, " +
31+
s"bestHash: ${Hex.toHexString(bestHash.toArray[Byte])}, " +
32+
s"genesisHash: ${Hex.toHexString(genesisHash.toArray[Byte])}," +
33+
s"forkId: $forkId," +
34+
s"}"
35+
36+
override def toShortString: String = toString
37+
override def code: Int = Codes.StatusCode
38+
}
39+
40+
object Status {
41+
implicit class StatusEnc(val underlyingMsg: Status)
42+
extends MessageSerializableImplicit[Status](underlyingMsg)
43+
with RLPSerializable {
44+
override def code: Int = Codes.StatusCode
45+
46+
override def toRLPEncodable: RLPEncodeable = {
47+
import msg._
48+
RLPList(protocolVersion, networkId, totalDifficulty, bestHash, genesisHash, forkId.toRLPEncodable)
49+
}
50+
}
51+
52+
implicit class StatusDec(val bytes: Array[Byte]) extends AnyVal {
53+
def toStatus: Status = rawDecode(bytes) match {
54+
case RLPList(
55+
protocolVersion,
56+
networkId,
57+
totalDifficulty,
58+
bestHash,
59+
genesisHash,
60+
forkId
61+
) =>
62+
Status(
63+
protocolVersion,
64+
networkId,
65+
totalDifficulty,
66+
bestHash,
67+
genesisHash,
68+
decode[ForkId](forkId)
69+
)
70+
71+
case _ => throw new RuntimeException("Cannot decode Status")
72+
}
73+
}
74+
}
75+
}

src/test/scala/io/iohk/ethereum/network/p2p/messages/MessagesSerializationSpec.scala

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
88

99
import io.iohk.ethereum.Fixtures
1010
import io.iohk.ethereum.domain.ChainWeight
11+
import io.iohk.ethereum.forkid.ForkId
1112
import io.iohk.ethereum.network.p2p.EthereumMessageDecoder
1213
import io.iohk.ethereum.network.p2p.NetworkMessageDecoder
1314
import io.iohk.ethereum.network.p2p.messages.BaseETH6XMessages._
@@ -56,13 +57,6 @@ class MessagesSerializationSpec extends AnyWordSpec with ScalaCheckPropertyCheck
5657
}
5758

5859
"Common Messages" when {
59-
"encoding and decoding Status" should {
60-
"return same result for Status v63" in {
61-
val msg = Status(1, 2, 2, ByteString("HASH"), ByteString("HASH2"))
62-
verify(msg, (m: Status) => m.toBytes, Codes.StatusCode, ProtocolVersions.ETH63)
63-
}
64-
}
65-
6660
"encoding and decoding SignedTransactions" should {
6761
"return same result" in {
6862
val msg = SignedTransactions(Fixtures.Blocks.Block3125369.body.transactionList)
@@ -96,6 +90,28 @@ class MessagesSerializationSpec extends AnyWordSpec with ScalaCheckPropertyCheck
9690

9791
"ETH63" when {
9892
val version = ProtocolVersions.ETH63
93+
"encoding and decoding Status" should {
94+
"return same result for Status v63" in {
95+
val msg = Status(1, 2, 2, ByteString("HASH"), ByteString("HASH2"))
96+
verify(msg, (m: Status) => m.toBytes, Codes.StatusCode, ProtocolVersions.ETH63)
97+
}
98+
}
99+
commonEthAssertions(version)
100+
}
101+
102+
"ETH64" when {
103+
val version = ProtocolVersions.ETH64
104+
"encoding and decoding Status" should {
105+
"return same result" in {
106+
val msg = ETH64.Status(1, 2, 3, ByteString("HASH"), ByteString("HASH2"), ForkId(1L, None))
107+
verify(msg, (m: ETH64.Status) => m.toBytes, Codes.StatusCode, ProtocolVersions.ETH64)
108+
}
109+
}
110+
commonEthAssertions(version)
111+
}
112+
113+
//scalastyle:off method.length
114+
def commonEthAssertions(version: Capability) = {
99115
"encoding and decoding ETH61.NewBlockHashes" should {
100116
"throw for unsupported message version" in {
101117
val msg = ETH61.NewBlockHashes(Seq(ByteString("23"), ByteString("10"), ByteString("36")))
@@ -157,6 +173,7 @@ class MessagesSerializationSpec extends AnyWordSpec with ScalaCheckPropertyCheck
157173
}
158174
}
159175
}
176+
//scalastyle:on
160177

161178
def verify[T](msg: T, encode: T => Array[Byte], code: Int, version: Capability): Unit =
162179
messageDecoder(version).fromBytes(code, encode(msg)) shouldEqual msg

0 commit comments

Comments
 (0)