Skip to content

Commit 0ce25c8

Browse files
committed
[ETCM-921] Introduce PrefixedRLPEncodable to handle binary prefixed RLP items
1 parent 76886fe commit 0ce25c8

File tree

3 files changed

+52
-36
lines changed

3 files changed

+52
-36
lines changed

rlp/src/main/scala/io/iohk/ethereum/rlp/RLP.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ private[rlp] object RLP {
113113
val inputAsBytes = value.bytes
114114
if (inputAsBytes.length == 1 && (inputAsBytes(0) & 0xff) < 0x80) inputAsBytes
115115
else encodeLength(inputAsBytes.length, OffsetShortItem) ++ inputAsBytes
116+
case PrefixedRLPEncodable(prefix, prefixedRLPEncodeable) =>
117+
prefix +: encode(prefixedRLPEncodeable)
116118
}
117119

118120
/** This function transform a byte into byte array

rlp/src/main/scala/io/iohk/ethereum/rlp/package.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ package object rlp {
4444
override def toString: String = s"RLPValue(${Hex.toHexString(bytes)})"
4545
}
4646

47+
case class PrefixedRLPEncodable(prefix: Byte, prefixedRLPEncodeable: RLPEncodeable) extends RLPEncodeable
48+
4749
trait RLPEncoder[T] {
4850
def encode(obj: T): RLPEncodeable
4951
}

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

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import io.iohk.ethereum.network.p2p.Message
1010
import io.iohk.ethereum.network.p2p.MessageSerializableImplicit
1111
import io.iohk.ethereum.rlp.RLPCodec.Ops
1212
import io.iohk.ethereum.rlp.RLPImplicitConversions._
13+
import io.iohk.ethereum.rlp.RLPImplicitDerivations.RLPListDecoder
1314
import io.iohk.ethereum.rlp.RLPImplicits._
1415
import io.iohk.ethereum.rlp._
1516
import io.iohk.ethereum.utils.ByteStringUtils.ByteStringOps
@@ -157,32 +158,29 @@ object BaseETH6XMessages {
157158

158159
implicit class SignedTransactionEnc(val signedTx: SignedTransaction) extends RLPSerializable {
159160

160-
override def toBytes: Array[Byte] =
161-
signedTx.tx match {
162-
// transaction with access list encoding is defined in eip2930
163-
case _: TransactionWithAccessList => Transaction.Type01 +: (super.toBytes: Array[Byte])
164-
case _: LegacyTransaction => super.toBytes
165-
}
166-
167161
override def toRLPEncodable: RLPEncodeable = {
168162
val receivingAddressBytes = signedTx.tx.receivingAddress
169163
.map(_.toArray)
170164
.getOrElse(Array.emptyByteArray)
171165
signedTx.tx match {
172166
case TransactionWithAccessList(chainId, nonce, gasPrice, gasLimit, _, value, payload, accessList) =>
173-
RLPList(
174-
chainId,
175-
nonce,
176-
gasPrice,
177-
gasLimit,
178-
receivingAddressBytes,
179-
value,
180-
payload,
181-
toRlpList(accessList),
182-
signedTx.signature.v,
183-
signedTx.signature.r,
184-
signedTx.signature.s
167+
PrefixedRLPEncodable(
168+
Transaction.Type01,
169+
RLPList(
170+
chainId,
171+
nonce,
172+
gasPrice,
173+
gasLimit,
174+
receivingAddressBytes,
175+
value,
176+
payload,
177+
toRlpList(accessList),
178+
signedTx.signature.v,
179+
signedTx.signature.r,
180+
signedTx.signature.s
181+
)
185182
)
183+
186184
case LegacyTransaction(nonce, gasPrice, gasLimit, _, value, payload) =>
187185
RLPList(
188186
nonce,
@@ -208,27 +206,40 @@ object BaseETH6XMessages {
208206
}
209207

210208
implicit class SignedTransactionsDec(val bytes: Array[Byte]) extends AnyVal {
211-
def toSignedTransactions: SignedTransactions = rawDecode(bytes) match {
212-
case rlpList: RLPList => SignedTransactions(rlpList.items.map(_.toSignedTransaction))
213-
case _ => throw new RuntimeException("Cannot decode SignedTransactions")
214-
}
209+
210+
def mergeTransactionType(encodables: Seq[RLPEncodeable]): Seq[RLPEncodeable] =
211+
encodables match {
212+
case Seq() => Seq()
213+
case Seq(RLPValue(v), rlpList: RLPList, tail @ _*) if v.length == 1 =>
214+
PrefixedRLPEncodable(v.head, rlpList) +: mergeTransactionType(tail)
215+
case Seq(head, tail @ _*) => head +: mergeTransactionType(tail)
216+
}
217+
def toSignedTransactions: SignedTransactions =
218+
rawDecode(bytes) match {
219+
case rlpList: RLPList => SignedTransactions(mergeTransactionType(rlpList.items).map(_.toSignedTransaction))
220+
case _ => throw new RuntimeException("Cannot decode SignedTransactions")
221+
}
215222
}
216223

217224
implicit class SignedTransactionRlpEncodableDec(val rlpEncodeable: RLPEncodeable) extends AnyVal {
218225

226+
// scalastyle:off method.length
219227
def toSignedTransaction: SignedTransaction = rlpEncodeable match {
220-
case RLPList(
221-
chainId,
222-
nonce,
223-
gasPrice,
224-
gasLimit,
225-
(receivingAddress: RLPValue),
226-
value,
227-
payload,
228-
(accessList: RLPList),
229-
pointSign,
230-
signatureRandom,
231-
signature
228+
case PrefixedRLPEncodable(
229+
Transaction.Type01,
230+
RLPList(
231+
chainId,
232+
nonce,
233+
gasPrice,
234+
gasLimit,
235+
(receivingAddress: RLPValue),
236+
value,
237+
payload,
238+
(accessList: RLPList),
239+
pointSign,
240+
signatureRandom,
241+
signature
242+
)
232243
) =>
233244
val receivingAddressOpt = if (receivingAddress.bytes.isEmpty) None else Some(Address(receivingAddress.bytes))
234245
SignedTransaction(
@@ -246,6 +257,7 @@ object BaseETH6XMessages {
246257
signatureRandom,
247258
signature
248259
)
260+
249261
case RLPList(
250262
nonce,
251263
gasPrice,
@@ -273,7 +285,7 @@ object BaseETH6XMessages {
273285
def toSignedTransaction: SignedTransaction = {
274286
val first = bytes(0)
275287
(first match {
276-
case Transaction.Type01 => rawDecode(bytes.tail)
288+
case Transaction.Type01 => PrefixedRLPEncodable(Transaction.Type01, rawDecode(bytes.tail))
277289
// TODO enforce legacy boundaries
278290
case _ => rawDecode(bytes)
279291
}).toSignedTransaction

0 commit comments

Comments
 (0)