Skip to content

Commit 7d47ca3

Browse files
author
lemastero
committed
[ETCM-126] add eth_pendingTransactions and remove qa_getPendingTransactions
Signed-off-by: lemastero <[email protected]>
1 parent 6cd26da commit 7d47ca3

File tree

9 files changed

+127
-189
lines changed

9 files changed

+127
-189
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,8 @@ class EthService(
576576
}
577577
})(Future.successful(OmmersPool.Ommers(Nil))) // NOTE If not Ethash consensus, ommers do not make sense, so => Nil
578578

579-
// TODO This seems to be re-implemented elsewhere, probably move to a better place? Also generalize the error message.
580-
private def getTransactionsFromPool: Future[PendingTransactionsResponse] = {
579+
// TODO This seems to be re-implemented elsewhere (TransactionPicker), probably move to a better place? Also generalize the error message.
580+
private[jsonrpc] def getTransactionsFromPool(): Future[PendingTransactionsResponse] = {
581581
implicit val timeout: Timeout = Timeout(getTransactionFromPoolTimeout)
582582

583583
(pendingTransactionsManager ? PendingTransactionsManager.GetPendingTransactions)

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import org.json4s.JsonDSL._
1111
import com.typesafe.config.{Config => TypesafeConfig}
1212
import io.iohk.ethereum.jsonrpc.DebugService.{ListPeersInfoRequest, ListPeersInfoResponse}
1313
import io.iohk.ethereum.jsonrpc.JsonRpcErrors.InvalidParams
14-
import io.iohk.ethereum.jsonrpc.QAService.{GetPendingTransactionsRequest, GetPendingTransactionsResponse}
1514
import io.iohk.ethereum.jsonrpc.TestService._
1615
import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer.JsonRpcHttpServerConfig
1716
import io.iohk.ethereum.jsonrpc.server.ipc.JsonRpcIpcServer.JsonRpcIpcServerConfig
@@ -346,9 +345,6 @@ class JsonRpcController(
346345
private def handleQARequest: PartialFunction[JsonRpcRequest, Future[JsonRpcResponse]] = {
347346
case req @ JsonRpcRequest(_, "qa_mineBlocks", _, _) =>
348347
handle[QAService.MineBlocksRequest, QAService.MineBlocksResponse](qaService.mineBlocks, req)
349-
350-
case req @ JsonRpcRequest(_, "qa_getPendingTransactions", _, _) =>
351-
handle[GetPendingTransactionsRequest, GetPendingTransactionsResponse](qaService.getPendingTransactions, req)
352348
}
353349

354350
private def handleRpcRequest: PartialFunction[JsonRpcRequest, Future[JsonRpcResponse]] = {

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

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

3-
import io.iohk.ethereum.jsonrpc.JsonRpcController.JsonDecoder.NoParamsDecoder
4-
import io.iohk.ethereum.jsonrpc.JsonRpcController.{Codec, JsonEncoder}
3+
import io.iohk.ethereum.jsonrpc.JsonRpcController.Codec
54
import io.iohk.ethereum.jsonrpc.JsonRpcErrors.InvalidParams
65
import io.iohk.ethereum.jsonrpc.QAService.{
7-
GetPendingTransactionsRequest,
8-
GetPendingTransactionsResponse,
96
MineBlocksRequest,
107
MineBlocksResponse
118
}
12-
import io.iohk.ethereum.transactions.PendingTransactionsManager.PendingTransaction
139
import org.json4s.JsonAST._
1410

1511
object QAJsonMethodsImplicits extends JsonMethodsImplicits {
@@ -36,12 +32,4 @@ object QAJsonMethodsImplicits extends JsonMethodsImplicits {
3632
"message" -> t.message.fold[JValue](JNull)(JString)
3733
)
3834
}
39-
40-
implicit val qa_getPendingTransactions: Codec[GetPendingTransactionsRequest, GetPendingTransactionsResponse] =
41-
new NoParamsDecoder(GetPendingTransactionsRequest()) with JsonEncoder[GetPendingTransactionsResponse] {
42-
def encodeJson(t: GetPendingTransactionsResponse): JValue =
43-
JArray(t.pendingTransactions.toList.map { pendingTx: PendingTransaction =>
44-
encodeAsHex(pendingTx.stx.tx.hash)
45-
})
46-
}
4735
}

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

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

3-
import akka.actor.ActorRef
3+
import akka.util.ByteString
44
import akka.util.ByteString
55
import cats.implicits._
66
import enumeratum._
77
import io.iohk.ethereum.consensus._
88
import io.iohk.ethereum.consensus.ethash.MinerResponses._
99
import io.iohk.ethereum.consensus.ethash.MockedMinerProtocol.MineBlocks
10-
import io.iohk.ethereum.consensus.ethash.{MinerResponse, MinerResponses, TransactionPicker}
10+
import io.iohk.ethereum.consensus.ethash.{MinerResponse, MinerResponses}
1111
import io.iohk.ethereum.jsonrpc.QAService.MineBlocksResponse.MinerResponseType
1212
import io.iohk.ethereum.jsonrpc.QAService.{
13-
GetPendingTransactionsRequest,
14-
GetPendingTransactionsResponse,
1513
MineBlocksRequest,
1614
MineBlocksResponse
1715
}
18-
import io.iohk.ethereum.transactions.PendingTransactionsManager.PendingTransaction
1916
import io.iohk.ethereum.utils.Logger
2017
import monix.execution.Scheduler.Implicits.global
2118
import mouse.all._
22-
import scala.concurrent.duration.FiniteDuration
2319

2420
class QAService(
25-
consensus: Consensus,
26-
val pendingTransactionsManager: ActorRef,
27-
val getTransactionFromPoolTimeout: FiniteDuration
28-
) extends Logger
29-
with TransactionPicker {
21+
consensus: Consensus
22+
) extends Logger {
3023

3124
/**
3225
* qa_mineBlocks that instructs mocked miner to mine given number of blocks
@@ -44,16 +37,6 @@ class QAService(
4437
Left(JsonRpcErrors.InternalError)
4538
}
4639
}
47-
48-
/**
49-
* qa_getPendingTransactions that returns all pending transactions from the mempool
50-
*
51-
* @return all pending transactions from the mempool
52-
*/
53-
def getPendingTransactions(req: GetPendingTransactionsRequest): ServiceResponse[GetPendingTransactionsResponse] =
54-
getTransactionsFromPool.map { resp =>
55-
Right(GetPendingTransactionsResponse(resp.pendingTransactions))
56-
}
5740
}
5841

5942
object QAService {
@@ -88,7 +71,4 @@ object QAService {
8871
}
8972
}
9073
}
91-
92-
case class GetPendingTransactionsRequest()
93-
case class GetPendingTransactionsResponse(pendingTransactions: Seq[PendingTransaction])
9474
}

src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -525,12 +525,7 @@ trait ShutdownHookBuilder {
525525
trait QaServiceBuilder {
526526
self: ConsensusBuilder with PendingTransactionsManagerBuilder with TxPoolConfigBuilder =>
527527

528-
lazy val qaService =
529-
new QAService(
530-
consensus,
531-
pendingTransactionsManager,
532-
txPoolConfig.getTransactionFromPoolTimeout
533-
)
528+
lazy val qaService = new QAService(consensus)
534529
}
535530

536531
object ShutdownHookBuilder extends ShutdownHookBuilder with Logger

src/test/scala/io/iohk/ethereum/jsonrpc/EthServiceSpec.scala

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import io.iohk.ethereum.blockchain.sync.EphemBlockchainTestSetup
99
import io.iohk.ethereum.consensus._
1010
import io.iohk.ethereum.consensus.blocks.{PendingBlock, PendingBlockAndState}
1111
import io.iohk.ethereum.consensus.ethash.blocks.EthashBlockGenerator
12+
import io.iohk.ethereum.crypto.ECDSASignature
1213
import io.iohk.ethereum.db.storage.AppStateStorage
1314
import io.iohk.ethereum.domain.{Address, Block, BlockHeader, BlockchainImpl, UInt256, _}
1415
import io.iohk.ethereum.jsonrpc.EthService.{ProtocolVersionRequest, _}
@@ -20,7 +21,7 @@ import io.iohk.ethereum.ledger.{Ledger, StxLedger}
2021
import io.iohk.ethereum.mpt.{ByteArrayEncoder, ByteArraySerializable, MerklePatriciaTrie}
2122
import io.iohk.ethereum.ommers.OmmersPool
2223
import io.iohk.ethereum.transactions.PendingTransactionsManager
23-
import io.iohk.ethereum.transactions.PendingTransactionsManager.{PendingTransaction, PendingTransactionsResponse}
24+
import io.iohk.ethereum.transactions.PendingTransactionsManager.{GetPendingTransactions, PendingTransaction, PendingTransactionsResponse}
2425
import io.iohk.ethereum.utils._
2526
import io.iohk.ethereum.{Fixtures, NormalPatience, Timeouts, crypto}
2627
import org.bouncycastle.util.encoders.Hex
@@ -1100,6 +1101,51 @@ class EthServiceSpec
11001101
response.futureValue shouldEqual Right(GetAccountTransactionsResponse(expectedSent))
11011102
}
11021103

1104+
it should "send message to pendingTransactionsManager and return an empty GetPendingTransactionsResponse" in new TestSetup {
1105+
val res = ethService.getTransactionsFromPool()
1106+
1107+
pendingTransactionsManager.expectMsg(GetPendingTransactions)
1108+
pendingTransactionsManager.reply(PendingTransactionsResponse(Nil))
1109+
1110+
res.futureValue shouldBe Right(PendingTransactionsResponse(Nil))
1111+
}
1112+
1113+
it should "send message to pendingTransactionsManager and return GetPendingTransactionsResponse with two transactions" in new TestSetup {
1114+
val transactions = (0 to 1)
1115+
.map(_ => {
1116+
val fakeTransaction = SignedTransactionWithSender(
1117+
Transaction(
1118+
nonce = 0,
1119+
gasPrice = 123,
1120+
gasLimit = 123,
1121+
receivingAddress = Address("0x1234"),
1122+
value = 0,
1123+
payload = ByteString()
1124+
),
1125+
signature = ECDSASignature(0, 0, 0.toByte),
1126+
sender = Address("0x1234")
1127+
)
1128+
PendingTransaction(fakeTransaction, System.currentTimeMillis)
1129+
})
1130+
.toList
1131+
1132+
val res = ethService.getTransactionsFromPool()
1133+
1134+
pendingTransactionsManager.expectMsg(GetPendingTransactions)
1135+
pendingTransactionsManager.reply(PendingTransactionsResponse(transactions))
1136+
1137+
res.futureValue shouldBe Right(PendingTransactionsResponse(transactions))
1138+
}
1139+
1140+
it should "send message to pendingTransactionsManager and return an empty GetPendingTransactionsResponse in case of error" in new TestSetup {
1141+
val res = ethService.getTransactionsFromPool()
1142+
1143+
pendingTransactionsManager.expectMsg(GetPendingTransactions)
1144+
pendingTransactionsManager.reply(new ClassCastException("error"))
1145+
1146+
res.futureValue shouldBe Right(PendingTransactionsResponse(Nil))
1147+
}
1148+
11031149
// NOTE TestSetup uses Ethash consensus; check `consensusConfig`.
11041150
trait TestSetup extends MockFactory with EphemBlockchainTestSetup {
11051151
val blockGenerator = mock[EthashBlockGenerator]

src/test/scala/io/iohk/ethereum/jsonrpc/JsonRpcControllerSpec.scala

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import io.iohk.ethereum.consensus.validators.SignedTransactionValidator
1313
import io.iohk.ethereum.consensus.{Consensus, ConsensusConfigs, TestConsensus}
1414
import io.iohk.ethereum.crypto.{ECDSASignature, kec256}
1515
import io.iohk.ethereum.db.storage.AppStateStorage
16-
import io.iohk.ethereum.domain.{Address, Block, BlockBody, BlockHeader, SignedTransaction}
16+
import io.iohk.ethereum.domain.{Address, Block, BlockBody, BlockHeader, SignedTransaction, SignedTransactionWithSender, Transaction}
1717
import io.iohk.ethereum.jsonrpc.DebugService.{ListPeersInfoRequest, ListPeersInfoResponse}
1818
import io.iohk.ethereum.jsonrpc.EthService._
1919
import io.iohk.ethereum.jsonrpc.FilterManager.{LogFilterLogs, TxLog}
@@ -31,6 +31,7 @@ import io.iohk.ethereum.network.p2p.messages.Versions
3131
import io.iohk.ethereum.ommers.OmmersPool
3232
import io.iohk.ethereum.ommers.OmmersPool.Ommers
3333
import io.iohk.ethereum.transactions.PendingTransactionsManager
34+
import io.iohk.ethereum.transactions.PendingTransactionsManager.PendingTransaction
3435
import io.iohk.ethereum.utils._
3536
import io.iohk.ethereum.{Fixtures, LongPatience, Timeouts}
3637
import org.bouncycastle.util.encoders.Hex
@@ -1901,6 +1902,71 @@ class JsonRpcControllerSpec
19011902
response should haveObjectResult("transactions" -> JArray(expectedTxs.toList))
19021903
}
19031904

1905+
"request pending transactions and return valid response" should "mempool is empty" in new TestSetup {
1906+
(ethService.ethPendingTransactions _)
1907+
.expects(EthPendingTransactionsRequest())
1908+
.returning(Future.successful(Right(EthPendingTransactionsResponse(List()))))
1909+
1910+
val request = JsonRpcRequest(
1911+
"2.0",
1912+
"eth_pendingTransactions",
1913+
Some(
1914+
JArray(
1915+
List()
1916+
)
1917+
),
1918+
Some(JInt(1))
1919+
)
1920+
1921+
val response: JsonRpcResponse = jsonRpcController.handleRequest(request).futureValue
1922+
1923+
response should haveResult(JArray(List()))
1924+
}
1925+
1926+
it should "mempool is empty" in new TestSetup {
1927+
val transactions = (0 to 1).map(_ => {
1928+
val fakeTransaction = SignedTransactionWithSender(
1929+
Transaction(
1930+
nonce = 0,
1931+
gasPrice = 123,
1932+
gasLimit = 123,
1933+
receivingAddress = Address("0x1234"),
1934+
value = 0,
1935+
payload = ByteString()
1936+
),
1937+
signature = ECDSASignature(0, 0, 0.toByte),
1938+
sender = Address("0x1234")
1939+
)
1940+
PendingTransaction(fakeTransaction, System.currentTimeMillis)
1941+
})
1942+
(ethService.ethPendingTransactions _)
1943+
.expects(EthPendingTransactionsRequest())
1944+
.returning(Future.successful(Right(EthPendingTransactionsResponse(transactions))))
1945+
1946+
val request = JsonRpcRequest(
1947+
"2.0",
1948+
"eth_pendingTransactions",
1949+
Some(
1950+
JArray(
1951+
List()
1952+
)
1953+
),
1954+
Some(JInt(1))
1955+
)
1956+
1957+
val response: JsonRpcResponse = jsonRpcController.handleRequest(request).futureValue
1958+
1959+
val result = JArray(
1960+
transactions
1961+
.map(tx => {
1962+
encodeAsHex(tx.stx.tx.hash)
1963+
})
1964+
.toList
1965+
)
1966+
1967+
response should haveResult(result)
1968+
}
1969+
19041970
trait TestSetup extends MockFactory with EphemBlockchainTestSetup with JsonMethodsImplicits {
19051971
def config: JsonRpcConfig = JsonRpcConfig(Config.config)
19061972

src/test/scala/io/iohk/ethereum/jsonrpc/QAServiceSpec.scala

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

33
import akka.actor.ActorSystem
4-
import akka.testkit.{TestKit, TestProbe}
5-
import akka.util.ByteString
4+
import akka.testkit.TestKit
65
import io.iohk.ethereum.consensus.Consensus
76
import io.iohk.ethereum.consensus.ethash.EthashConfig
87
import io.iohk.ethereum.consensus.ethash.MinerResponses.MiningOrdered
98
import io.iohk.ethereum.consensus.ethash.MockedMinerProtocol.MineBlocks
10-
import io.iohk.ethereum.crypto.ECDSASignature
11-
import io.iohk.ethereum.domain.{Address, SignedTransactionWithSender, Transaction}
12-
import io.iohk.ethereum.jsonrpc.QAService.{
13-
GetPendingTransactionsRequest,
14-
GetPendingTransactionsResponse,
15-
MineBlocksRequest,
16-
MineBlocksResponse
17-
}
18-
import io.iohk.ethereum.transactions.PendingTransactionsManager.{
19-
GetPendingTransactions,
20-
PendingTransaction,
21-
PendingTransactionsResponse
22-
}
23-
import io.iohk.ethereum.{ByteGenerators, FlatSpecBase, SpecFixtures, Timeouts}
9+
import io.iohk.ethereum.jsonrpc.QAService.{MineBlocksRequest, MineBlocksResponse}
10+
import io.iohk.ethereum.{ByteGenerators, FlatSpecBase, SpecFixtures}
2411
import org.scalamock.scalatest.AsyncMockFactory
12+
2513
import scala.concurrent.Future
26-
import scala.concurrent.duration.FiniteDuration
2714

2815
class QAServiceSpec
2916
extends TestKit(ActorSystem("QAServiceSpec_System"))
@@ -56,70 +43,13 @@ class QAServiceSpec
5643
qaService.mineBlocks(mineBlocksReq).map(_ shouldBe Left(JsonRpcErrors.InternalError))
5744
}
5845

59-
it should "send message to pendingTransactionsManager and return an empty GetPendingTransactionsResponse" in testCaseF {
60-
fixture =>
61-
import fixture._
62-
val res = qaService.getPendingTransactions(GetPendingTransactionsRequest())
63-
64-
pendingTransactionsManager.expectMsg(GetPendingTransactions)
65-
pendingTransactionsManager.reply(PendingTransactionsResponse(Nil))
66-
67-
res.map(_ shouldBe Right(GetPendingTransactionsResponse(Nil)))
68-
}
69-
70-
it should "send message to pendingTransactionsManager and return GetPendingTransactionsResponse with two transactions" in testCaseF {
71-
fixture =>
72-
import fixture._
73-
val transactions = (0 to 1)
74-
.map(_ => {
75-
val fakeTransaction = SignedTransactionWithSender(
76-
Transaction(
77-
nonce = 0,
78-
gasPrice = 123,
79-
gasLimit = 123,
80-
receivingAddress = Address("0x1234"),
81-
value = 0,
82-
payload = ByteString()
83-
),
84-
signature = ECDSASignature(0, 0, 0.toByte),
85-
sender = Address("0x1234")
86-
)
87-
PendingTransaction(fakeTransaction, System.currentTimeMillis)
88-
})
89-
.toList
90-
91-
val res = qaService.getPendingTransactions(GetPendingTransactionsRequest())
92-
93-
pendingTransactionsManager.expectMsg(GetPendingTransactions)
94-
pendingTransactionsManager.reply(PendingTransactionsResponse(transactions))
95-
96-
res.map(_ shouldBe Right(GetPendingTransactionsResponse(transactions)))
97-
}
98-
99-
it should "send message to pendingTransactionsManager and return an empty GetPendingTransactionsResponse in case of error" in testCaseF {
100-
fixture =>
101-
import fixture._
102-
val res = qaService.getPendingTransactions(GetPendingTransactionsRequest())
103-
104-
pendingTransactionsManager.expectMsg(GetPendingTransactions)
105-
pendingTransactionsManager.reply(new ClassCastException("error"))
106-
107-
res.map(_ shouldBe Right(GetPendingTransactionsResponse(Nil)))
108-
}
109-
11046
class Fixture {
11147
protected trait TestConsensus extends Consensus {
11248
override type Config = EthashConfig
11349
}
11450

11551
lazy val testConsensus: TestConsensus = mock[TestConsensus]
116-
lazy val pendingTransactionsManager = TestProbe()
117-
lazy val getTransactionFromPoolTimeout: FiniteDuration = Timeouts.normalTimeout
118-
lazy val qaService = new QAService(
119-
testConsensus,
120-
pendingTransactionsManager.ref,
121-
getTransactionFromPoolTimeout
122-
)
52+
lazy val qaService = new QAService(testConsensus)
12353

12454
lazy val mineBlocksReq = MineBlocksRequest(1, true, None)
12555
lazy val mineBlocksMsg =

0 commit comments

Comments
 (0)