Skip to content

Commit b3165d2

Browse files
committed
[ETCM-139] Fix json rpc error serialization, json4s - thank you for being so unhelpful there
1 parent d1acb6f commit b3165d2

20 files changed

+215
-170
lines changed

build.sbt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,12 @@ val root = {
6868
libraryDependencies ++= dep
6969
)
7070
.settings(executableScriptName := name.value)
71-
.settings(inConfig(Integration)(Defaults.testSettings
72-
++ org.scalafmt.sbt.ScalafmtPlugin.scalafmtConfigSettings :+ (Test / parallelExecution := false)): _*)
71+
.settings(
72+
inConfig(Integration)(
73+
Defaults.testSettings
74+
++ org.scalafmt.sbt.ScalafmtPlugin.scalafmtConfigSettings :+ (Test / parallelExecution := false)
75+
): _*
76+
)
7377
.settings(inConfig(Benchmark)(Defaults.testSettings :+ (Test / parallelExecution := false)): _*)
7478
.settings(inConfig(Evm)(Defaults.testSettings :+ (Test / parallelExecution := false)): _*)
7579
.settings(inConfig(Ets)(Defaults.testSettings :+ (Test / parallelExecution := false)): _*)
@@ -158,8 +162,8 @@ addCommandAlias(
158162
addCommandAlias(
159163
"pp",
160164
""";compile-all
161-
|;test
162165
|;scalastyle
163166
|;test:scalastyle
167+
|;test
164168
|""".stripMargin
165169
)

src/main/scala/io/iohk/ethereum/jsonrpc/CheckpointingJsonMethodsImplicits.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ package io.iohk.ethereum.jsonrpc
33
import akka.util.ByteString
44
import io.iohk.ethereum.crypto.ECDSASignature
55
import io.iohk.ethereum.jsonrpc.CheckpointingService._
6-
import io.iohk.ethereum.jsonrpc.JsonRpcController.Codec
76
import io.iohk.ethereum.jsonrpc.JsonRpcError.InvalidParams
8-
import io.iohk.ethereum.jsonrpc.JsonSerializers.QuantitiesSerializer
7+
import io.iohk.ethereum.jsonrpc.serialization.JsonMethodCodec
8+
import io.iohk.ethereum.jsonrpc.serialization.JsonSerializers.QuantitiesSerializer
99
import org.json4s.JsonAST._
1010
import org.json4s.{Extraction, JsonAST}
1111

1212
object CheckpointingJsonMethodsImplicits extends JsonMethodsImplicits {
1313

14-
implicit val checkpointing_getLatestBlock: Codec[GetLatestBlockRequest, GetLatestBlockResponse] =
15-
new Codec[GetLatestBlockRequest, GetLatestBlockResponse] {
14+
implicit val checkpointing_getLatestBlock: JsonMethodCodec[GetLatestBlockRequest, GetLatestBlockResponse] =
15+
new JsonMethodCodec[GetLatestBlockRequest, GetLatestBlockResponse] {
1616
override def decodeJson(
1717
params: Option[JsonAST.JArray]
1818
): Either[JsonRpcError, GetLatestBlockRequest] =
@@ -30,8 +30,8 @@ object CheckpointingJsonMethodsImplicits extends JsonMethodsImplicits {
3030
Extraction.decompose(resp)(formats - QuantitiesSerializer)
3131
}
3232

33-
implicit val checkpointing_pushCheckpoint: Codec[PushCheckpointRequest, PushCheckpointResponse] =
34-
new Codec[PushCheckpointRequest, PushCheckpointResponse] {
33+
implicit val checkpointing_pushCheckpoint: JsonMethodCodec[PushCheckpointRequest, PushCheckpointResponse] =
34+
new JsonMethodCodec[PushCheckpointRequest, PushCheckpointResponse] {
3535
override def decodeJson(
3636
params: Option[JsonAST.JArray]
3737
): Either[JsonRpcError, PushCheckpointRequest] =

src/main/scala/io/iohk/ethereum/jsonrpc/DebugJsonMethodsImplicits.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
package io.iohk.ethereum.jsonrpc
22

33
import io.iohk.ethereum.jsonrpc.DebugService.{ListPeersInfoRequest, ListPeersInfoResponse}
4-
import io.iohk.ethereum.jsonrpc.JsonRpcController.{Codec, JsonEncoder}
5-
import io.iohk.ethereum.jsonrpc.JsonRpcController.JsonDecoder.NoParamsDecoder
4+
import io.iohk.ethereum.jsonrpc.serialization.JsonMethodDecoder.NoParamsMethodDecoder
5+
import io.iohk.ethereum.jsonrpc.serialization.{JsonEncoder, JsonMethodCodec}
66
import org.json4s.JsonAST.{JArray, JString, JValue}
77

88
object DebugJsonMethodsImplicits extends JsonMethodsImplicits {
99

10-
implicit val debug_listPeersInfo: Codec[ListPeersInfoRequest, ListPeersInfoResponse] =
11-
new NoParamsDecoder(ListPeersInfoRequest()) with JsonEncoder[ListPeersInfoResponse] {
10+
implicit val debug_listPeersInfo: JsonMethodCodec[ListPeersInfoRequest, ListPeersInfoResponse] =
11+
new NoParamsMethodDecoder(ListPeersInfoRequest()) with JsonEncoder[ListPeersInfoResponse] {
1212
def encodeJson(t: ListPeersInfoResponse): JValue =
1313
JArray(t.peers.map(a => JString(a.toString)))
1414
}

src/main/scala/io/iohk/ethereum/jsonrpc/EthJsonMethodsImplicits.scala

Lines changed: 52 additions & 46 deletions
Large diffs are not rendered by default.

src/main/scala/io/iohk/ethereum/jsonrpc/IeleJsonMethodsImplicits.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ package io.iohk.ethereum.jsonrpc
22

33
import akka.util.ByteString
44
import io.iohk.ethereum.jsonrpc.EthService._
5-
import io.iohk.ethereum.jsonrpc.JsonRpcController.{JsonDecoder, JsonEncoder}
65
import io.iohk.ethereum.jsonrpc.JsonRpcError.InvalidParams
76
import io.iohk.ethereum.jsonrpc.PersonalService.{InvalidAddress, SendIeleTransactionRequest}
7+
import io.iohk.ethereum.jsonrpc.serialization.{JsonEncoder, JsonMethodDecoder}
88
import org.json4s.JsonAST.{JArray, JObject, JString, JValue}
99

1010
object IeleJsonMethodsImplicits extends JsonMethodsImplicits {
@@ -34,7 +34,7 @@ object IeleJsonMethodsImplicits extends JsonMethodsImplicits {
3434
)
3535
}
3636

37-
implicit val iele_call = new JsonDecoder[IeleCallRequest] with JsonEncoder[IeleCallResponse] {
37+
implicit val iele_call = new JsonMethodDecoder[IeleCallRequest] with JsonEncoder[IeleCallResponse] {
3838
def decodeJson(params: Option[JArray]): Either[JsonRpcError, IeleCallRequest] =
3939
params match {
4040
case Some(JArray((txObj: JObject) :: (blockValue: JValue) :: Nil)) =>
@@ -93,7 +93,7 @@ object IeleJsonMethodsImplicits extends JsonMethodsImplicits {
9393
} yield IeleTransactionRequest(from, to, value, gas, gasPrice, nonce, function, arguments, contractCode)
9494
}
9595

96-
implicit val iele_sendTransaction = new JsonDecoder[SendIeleTransactionRequest] {
96+
implicit val iele_sendTransaction = new JsonMethodDecoder[SendIeleTransactionRequest] {
9797
def decodeJson(params: Option[JArray]): Either[JsonRpcError, SendIeleTransactionRequest] =
9898
params match {
9999
case Some(JArray(JObject(tx) :: _)) =>

src/main/scala/io/iohk/ethereum/jsonrpc/JsonMethodsImplicits.scala

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,21 @@ import akka.util.ByteString
66
import io.iohk.ethereum.crypto.ECDSASignature
77
import io.iohk.ethereum.domain.Address
88
import io.iohk.ethereum.jsonrpc.EthService.BlockParam
9-
import io.iohk.ethereum.jsonrpc.JsonRpcController.JsonDecoder.NoParamsDecoder
10-
import io.iohk.ethereum.jsonrpc.JsonRpcController.{Codec, JsonDecoder, JsonEncoder}
119
import io.iohk.ethereum.jsonrpc.JsonRpcError.InvalidParams
12-
import io.iohk.ethereum.jsonrpc.JsonSerializers.{
13-
AddressJsonSerializer,
14-
OptionNoneToJNullSerializer,
15-
QuantitiesSerializer,
16-
UnformattedDataJsonSerializer
17-
}
1810
import io.iohk.ethereum.jsonrpc.NetService._
1911
import io.iohk.ethereum.jsonrpc.PersonalService._
2012
import io.iohk.ethereum.jsonrpc.Web3Service.{ClientVersionRequest, ClientVersionResponse, Sha3Request, Sha3Response}
13+
import io.iohk.ethereum.jsonrpc.serialization.JsonMethodDecoder.NoParamsMethodDecoder
14+
import io.iohk.ethereum.jsonrpc.serialization.{JsonEncoder, JsonMethodCodec, JsonMethodDecoder, JsonSerializers}
2115
import io.iohk.ethereum.utils.BigIntExtensionMethods.BigIntAsUnsigned
16+
import org.bouncycastle.util.encoders.Hex
2217
import org.json4s.JsonAST._
2318
import org.json4s.JsonDSL._
24-
import org.json4s.{DefaultFormats, Formats}
25-
import org.bouncycastle.util.encoders.Hex
2619

2720
import scala.util.Try
2821

2922
trait JsonMethodsImplicits {
30-
31-
implicit val formats: Formats = DefaultFormats.preservingEmptyValues + OptionNoneToJNullSerializer +
32-
QuantitiesSerializer + UnformattedDataJsonSerializer + AddressJsonSerializer
23+
implicit val formats = JsonSerializers.formats
3324

3425
protected def encodeAsHex(input: ByteString): JString =
3526
JString(s"0x${Hex.toHexString(input.toArray[Byte])}")
@@ -154,7 +145,7 @@ object JsonMethodsImplicits extends JsonMethodsImplicits {
154145

155146
import JsonRpcError._
156147

157-
implicit val web3_sha3 = new JsonDecoder[Sha3Request] with JsonEncoder[Sha3Response] {
148+
implicit val web3_sha3 = new JsonMethodDecoder[Sha3Request] with JsonEncoder[Sha3Response] {
158149
override def decodeJson(params: Option[JArray]): Either[JsonRpcError, Sha3Request] =
159150
params match {
160151
case Some(JArray((input: JString) :: Nil)) => extractBytes(input).map(Sha3Request)
@@ -164,24 +155,25 @@ object JsonMethodsImplicits extends JsonMethodsImplicits {
164155
override def encodeJson(t: Sha3Response): JValue = encodeAsHex(t.data)
165156
}
166157

167-
implicit val web3_clientVersion = new NoParamsDecoder(ClientVersionRequest())
158+
implicit val web3_clientVersion = new NoParamsMethodDecoder(ClientVersionRequest())
168159
with JsonEncoder[ClientVersionResponse] {
169160
override def encodeJson(t: ClientVersionResponse): JValue = t.value
170161
}
171162

172-
implicit val net_version = new NoParamsDecoder(VersionRequest()) with JsonEncoder[VersionResponse] {
163+
implicit val net_version = new NoParamsMethodDecoder(VersionRequest()) with JsonEncoder[VersionResponse] {
173164
override def encodeJson(t: VersionResponse): JValue = t.value
174165
}
175166

176-
implicit val net_listening = new NoParamsDecoder(ListeningRequest()) with JsonEncoder[ListeningResponse] {
167+
implicit val net_listening = new NoParamsMethodDecoder(ListeningRequest()) with JsonEncoder[ListeningResponse] {
177168
override def encodeJson(t: ListeningResponse): JValue = t.value
178169
}
179170

180-
implicit val net_peerCount = new NoParamsDecoder(PeerCountRequest()) with JsonEncoder[PeerCountResponse] {
171+
implicit val net_peerCount = new NoParamsMethodDecoder(PeerCountRequest()) with JsonEncoder[PeerCountResponse] {
181172
override def encodeJson(t: PeerCountResponse): JValue = encodeAsHex(t.value)
182173
}
183174

184-
implicit val personal_importRawKey = new JsonDecoder[ImportRawKeyRequest] with JsonEncoder[ImportRawKeyResponse] {
175+
implicit val personal_importRawKey = new JsonMethodDecoder[ImportRawKeyRequest]
176+
with JsonEncoder[ImportRawKeyResponse] {
185177
def decodeJson(params: Option[JArray]): Either[JsonRpcError, ImportRawKeyRequest] =
186178
params match {
187179
case Some(JArray(JString(key) :: JString(passphrase) :: _)) =>
@@ -194,7 +186,7 @@ object JsonMethodsImplicits extends JsonMethodsImplicits {
194186
JString(t.address.toString)
195187
}
196188

197-
implicit val personal_newAccount = new JsonDecoder[NewAccountRequest] with JsonEncoder[NewAccountResponse] {
189+
implicit val personal_newAccount = new JsonMethodDecoder[NewAccountRequest] with JsonEncoder[NewAccountResponse] {
198190
def decodeJson(params: Option[JArray]): Either[JsonRpcError, NewAccountRequest] =
199191
params match {
200192
case Some(JArray(JString(passphrase) :: _)) =>
@@ -207,14 +199,14 @@ object JsonMethodsImplicits extends JsonMethodsImplicits {
207199
JString(t.address.toString)
208200
}
209201

210-
implicit val personal_listAccounts = new NoParamsDecoder(ListAccountsRequest())
202+
implicit val personal_listAccounts = new NoParamsMethodDecoder(ListAccountsRequest())
211203
with JsonEncoder[ListAccountsResponse] {
212204
def encodeJson(t: ListAccountsResponse): JValue =
213205
JArray(t.addresses.map(a => JString(a.toString)))
214206
}
215207

216208
implicit val personal_sendTransaction =
217-
new Codec[SendTransactionWithPassphraseRequest, SendTransactionWithPassphraseResponse] {
209+
new JsonMethodCodec[SendTransactionWithPassphraseRequest, SendTransactionWithPassphraseResponse] {
218210
def decodeJson(params: Option[JArray]): Either[JsonRpcError, SendTransactionWithPassphraseRequest] =
219211
params match {
220212
case Some(JArray(JObject(tx) :: JString(passphrase) :: _)) =>
@@ -227,7 +219,7 @@ object JsonMethodsImplicits extends JsonMethodsImplicits {
227219
encodeAsHex(t.txHash)
228220
}
229221

230-
implicit val personal_sign = new Codec[SignRequest, SignResponse] {
222+
implicit val personal_sign = new JsonMethodCodec[SignRequest, SignResponse] {
231223
override def encodeJson(t: SignResponse): JValue = {
232224
import t.signature._
233225
encodeAsHex(ByteString(r.toUnsignedByteArray ++ s.toUnsignedByteArray :+ v))
@@ -245,7 +237,7 @@ object JsonMethodsImplicits extends JsonMethodsImplicits {
245237
}
246238
}
247239

248-
implicit val personal_ecRecover = new Codec[EcRecoverRequest, EcRecoverResponse] {
240+
implicit val personal_ecRecover = new JsonMethodCodec[EcRecoverRequest, EcRecoverResponse] {
249241

250242
def decodeJson(params: Option[JArray]): Either[JsonRpcError, EcRecoverRequest] =
251243
params match {
@@ -274,7 +266,7 @@ object JsonMethodsImplicits extends JsonMethodsImplicits {
274266
encodeAsHex(t.address.bytes)
275267
}
276268

277-
implicit val personal_unlockAccount = new Codec[UnlockAccountRequest, UnlockAccountResponse] {
269+
implicit val personal_unlockAccount = new JsonMethodCodec[UnlockAccountRequest, UnlockAccountResponse] {
278270
def decodeJson(params: Option[JArray]): Either[JsonRpcError, UnlockAccountRequest] = {
279271
params match {
280272
case Some(JArray(JString(addr) :: JString(passphrase) :: JNull :: _)) =>
@@ -295,7 +287,7 @@ object JsonMethodsImplicits extends JsonMethodsImplicits {
295287
JBool(t.result)
296288
}
297289

298-
implicit val personal_lockAccount = new Codec[LockAccountRequest, LockAccountResponse] {
290+
implicit val personal_lockAccount = new JsonMethodCodec[LockAccountRequest, LockAccountResponse] {
299291
def decodeJson(params: Option[JArray]): Either[JsonRpcError, LockAccountRequest] = {
300292
params match {
301293
case Some(JArray(JString(addr) :: _)) =>

src/main/scala/io/iohk/ethereum/jsonrpc/JsonRpcController.scala

Lines changed: 15 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,34 @@
11
package io.iohk.ethereum.jsonrpc
22

3+
import java.util.concurrent.TimeUnit
4+
5+
import com.typesafe.config.{Config => TypesafeConfig}
6+
import io.iohk.ethereum.jsonrpc.CheckpointingService._
7+
import io.iohk.ethereum.jsonrpc.DebugService.{ListPeersInfoRequest, ListPeersInfoResponse}
38
import io.iohk.ethereum.jsonrpc.EthService._
49
import io.iohk.ethereum.jsonrpc.JsonRpcController.JsonRpcConfig
510
import io.iohk.ethereum.jsonrpc.NetService._
611
import io.iohk.ethereum.jsonrpc.PersonalService._
7-
import io.iohk.ethereum.jsonrpc.Web3Service._
8-
import io.iohk.ethereum.utils.Logger
9-
import org.json4s.JsonAST.{JArray, JValue}
10-
import org.json4s.JsonDSL._
11-
import com.typesafe.config.{Config => TypesafeConfig}
12-
import io.iohk.ethereum.jsonrpc.DebugService.{ListPeersInfoRequest, ListPeersInfoResponse}
13-
import io.iohk.ethereum.jsonrpc.JsonRpcError.InvalidParams
1412
import io.iohk.ethereum.jsonrpc.QAService.{
1513
GenerateCheckpointRequest,
1614
GenerateCheckpointResponse,
1715
GetFederationMembersInfoRequest,
1816
GetFederationMembersInfoResponse
1917
}
2018
import io.iohk.ethereum.jsonrpc.TestService._
19+
import io.iohk.ethereum.jsonrpc.Web3Service._
20+
import io.iohk.ethereum.jsonrpc.serialization.{JsonEncoder, JsonMethodDecoder}
2121
import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer.JsonRpcHttpServerConfig
2222
import io.iohk.ethereum.jsonrpc.server.ipc.JsonRpcIpcServer.JsonRpcIpcServerConfig
23-
import java.util.concurrent.TimeUnit
24-
25-
import io.iohk.ethereum.jsonrpc.CheckpointingService._
23+
import io.iohk.ethereum.utils.Logger
24+
import org.json4s.JsonDSL._
2625

27-
import scala.concurrent.Future
2826
import scala.concurrent.ExecutionContext.Implicits.global
27+
import scala.concurrent.Future
2928
import scala.concurrent.duration.FiniteDuration
3029
import scala.util.{Failure, Success}
3130

3231
object JsonRpcController {
33-
34-
trait JsonDecoder[T] {
35-
def decodeJson(params: Option[JArray]): Either[JsonRpcError, T]
36-
}
37-
object JsonDecoder {
38-
abstract class NoParamsDecoder[T](request: => T) extends JsonDecoder[T] {
39-
def decodeJson(params: Option[JArray]): Either[JsonRpcError, T] =
40-
params match {
41-
case None | Some(JArray(Nil)) => Right(request)
42-
case _ => Left(InvalidParams(s"No parameters expected"))
43-
}
44-
}
45-
}
46-
47-
trait JsonEncoder[T] {
48-
def encodeJson(t: T): JValue
49-
}
50-
object JsonEncoder {
51-
def apply[T](implicit encoder: JsonEncoder[T]): JsonEncoder[T] = encoder
52-
53-
implicit def listEncoder[T](implicit itemEncoder: JsonEncoder[T]): JsonEncoder[List[T]] = list =>
54-
JArray(list.map(itemEncoder.encodeJson))
55-
}
56-
57-
trait Codec[Req, Res] extends JsonDecoder[Req] with JsonEncoder[Res]
58-
object Codec {
59-
import scala.language.implicitConversions
60-
61-
implicit def decoderWithEncoderIntoCodec[Req, Res](
62-
decEnc: JsonDecoder[Req] with JsonEncoder[Res]
63-
): Codec[Req, Res] = new Codec[Req, Res] {
64-
def decodeJson(params: Option[JArray]) = decEnc.decodeJson(params)
65-
def encodeJson(t: Res) = decEnc.encodeJson(t)
66-
}
67-
}
68-
6932
trait JsonRpcConfig {
7033
def apis: Seq[String]
7134
def accountTransactionsMaxBlocks: Int
@@ -127,15 +90,15 @@ class JsonRpcController(
12790
config: JsonRpcConfig
12891
) extends Logger {
12992

130-
import JsonRpcController._
93+
import CheckpointingJsonMethodsImplicits._
94+
import DebugJsonMethodsImplicits._
13195
import EthJsonMethodsImplicits._
132-
import TestJsonMethodsImplicits._
13396
import IeleJsonMethodsImplicits._
13497
import JsonMethodsImplicits._
98+
import JsonRpcController._
13599
import JsonRpcError._
136-
import DebugJsonMethodsImplicits._
137100
import QAJsonMethodsImplicits._
138-
import CheckpointingJsonMethodsImplicits._
101+
import TestJsonMethodsImplicits._
139102

140103
lazy val apisHandleFns: Map[String, PartialFunction[JsonRpcRequest, Future[JsonRpcResponse]]] = Map(
141104
Apis.Eth -> handleEthRequest,
@@ -415,7 +378,7 @@ class JsonRpcController(
415378
private def handle[Req, Res](
416379
fn: Req => Future[Either[JsonRpcError, Res]],
417380
rpcReq: JsonRpcRequest
418-
)(implicit dec: JsonDecoder[Req], enc: JsonEncoder[Res]): Future[JsonRpcResponse] = {
381+
)(implicit dec: JsonMethodDecoder[Req], enc: JsonEncoder[Res]): Future[JsonRpcResponse] = {
419382
dec.decodeJson(rpcReq.params) match {
420383
case Right(req) =>
421384
fn(req)

src/main/scala/io/iohk/ethereum/jsonrpc/JsonRpcError.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package io.iohk.ethereum.jsonrpc
22

33
import io.iohk.ethereum.consensus.Protocol
4-
import io.iohk.ethereum.jsonrpc.JsonRpcController.JsonEncoder
5-
import org.json4s.{JInt, JString, JObject, JValue}
4+
import io.iohk.ethereum.jsonrpc.serialization.JsonEncoder
5+
import org.json4s.{JInt, JObject, JString, JValue}
66

77
case class JsonRpcError(code: Int, message: String, data: Option[JValue])
88

@@ -12,6 +12,12 @@ object JsonRpcError {
1212
def apply[T: JsonEncoder](code: Int, message: String, data: T): JsonRpcError =
1313
JsonRpcError(code, message, Some(JsonEncoder[T].encodeJson(data)))
1414

15+
implicit val jsonRpcErrorEncoder: JsonEncoder[JsonRpcError] = err =>
16+
JObject(
17+
List("code" -> JsonEncoder.encode(err.code), "message" -> JsonEncoder.encode(err.message)) ++
18+
err.data.map("data" -> _)
19+
)
20+
1521
val ParseError = JsonRpcError(-32700, "An error occurred on the server while parsing the JSON text", None)
1622
val InvalidRequest = JsonRpcError(-32600, "The JSON sent is not a valid Request object", None)
1723
val MethodNotFound = JsonRpcError(-32601, "The method does not exist / is not available", None)

0 commit comments

Comments
 (0)