Skip to content

Commit 6e3c185

Browse files
committed
Merge remote-tracking branch 'origin/develop' into etcm-103/restartable-state-sync
2 parents b60038a + 5fb0b41 commit 6e3c185

16 files changed

+1790
-2098
lines changed

build.sbt

+10
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,13 @@ addCommandAlias(
146146
|;benchmark:compile
147147
|""".stripMargin
148148
)
149+
150+
// prepare PR
151+
addCommandAlias(
152+
"pp",
153+
""";compile-all
154+
|;test
155+
|;scalastyle
156+
|;test:scalastyle
157+
|""".stripMargin
158+
)

insomnia_workspace.json

+37-37
Original file line numberDiff line numberDiff line change
@@ -139,43 +139,6 @@
139139
"metaSortKey": -1600249374160,
140140
"_type": "request_group"
141141
},
142-
{
143-
"_id": "req_6197fefa1e1448a89f30712ec12295f8",
144-
"parentId": "fld_2b54cbb84e244284b3ef752c5f805376",
145-
"modified": 1600249571669,
146-
"created": 1600249491560,
147-
"url": "{{ node_url }}",
148-
"name": "qa_getPendingTransactions",
149-
"description": "",
150-
"method": "POST",
151-
"body": {
152-
"mimeType": "application/json",
153-
"text": "{\n\t\"jsonrpc\": \"2.0\",\n \"method\": \"qa_getPendingTransactions\", \n \"params\": [],\n \"id\": 1\n}"
154-
},
155-
"parameters": [],
156-
"headers": [
157-
{
158-
"id": "pair_9f4d6a9dde554cd384487e04fa3b21aa",
159-
"name": "Content-Type",
160-
"value": "application/json"
161-
},
162-
{
163-
"id": "pair_088edc31f5e04f20a16b465a673871bb",
164-
"name": "Cache-Control",
165-
"value": "no-cache"
166-
}
167-
],
168-
"authentication": {},
169-
"metaSortKey": -1552939150156.832,
170-
"isPrivate": false,
171-
"settingStoreCookies": true,
172-
"settingSendCookies": true,
173-
"settingDisableRenderRequestBody": false,
174-
"settingEncodeUrl": true,
175-
"settingRebuildPath": true,
176-
"settingFollowRedirects": "global",
177-
"_type": "request"
178-
},
179142
{
180143
"_id": "req_dd6e5c718f974407bb79fe3c953b7106",
181144
"parentId": "fld_72829b866f0441e184e0d1a2030f8220",
@@ -961,6 +924,43 @@
961924
"settingFollowRedirects": "global",
962925
"_type": "request"
963926
},
927+
{
928+
"_id": "req_4c1135a4a69644fe9850292131197b47",
929+
"parentId": "fld_a06eb77e183c4727800eb7dc43ceabe1",
930+
"modified": 1602234543563,
931+
"created": 1602234438767,
932+
"url": "{{ node_url }}",
933+
"name": "eth_pendingTransactions",
934+
"description": "Returns the transactions that are pending in the transaction pool and have a from address that is one of the accounts this node manages",
935+
"method": "POST",
936+
"body": {
937+
"mimeType": "application/json",
938+
"text": "{\n\t\"jsonrpc\": \"2.0\",\n \"method\": \"eth_pendingTransactions\", \n\t\"params\": [],\n \"id\": 1\n}"
939+
},
940+
"parameters": [],
941+
"headers": [
942+
{
943+
"id": "pair_9f4d6a9dde554cd384487e04fa3b21aa",
944+
"name": "Content-Type",
945+
"value": "application/json"
946+
},
947+
{
948+
"id": "pair_088edc31f5e04f20a16b465a673871bb",
949+
"name": "Cache-Control",
950+
"value": "no-cache"
951+
}
952+
],
953+
"authentication": {},
954+
"metaSortKey": -1552732410719.375,
955+
"isPrivate": false,
956+
"settingStoreCookies": true,
957+
"settingSendCookies": true,
958+
"settingDisableRenderRequestBody": false,
959+
"settingEncodeUrl": true,
960+
"settingRebuildPath": true,
961+
"settingFollowRedirects": "global",
962+
"_type": "request"
963+
},
964964
{
965965
"_id": "req_579a127b434b4ac7aa51ee6c93f04630",
966966
"parentId": "fld_a06eb77e183c4727800eb7dc43ceabe1",

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

+9
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,15 @@ object EthJsonMethodsImplicits extends JsonMethodsImplicits {
125125
Extraction.decompose(t.blockResponse)
126126
}
127127

128+
implicit val eth_pendingTransactions = new NoParamsDecoder(EthPendingTransactionsRequest())
129+
with JsonEncoder[EthPendingTransactionsResponse] {
130+
131+
override def encodeJson(t: EthPendingTransactionsResponse): JValue =
132+
JArray(t.pendingTransactions.toList.map { pendingTx =>
133+
encodeAsHex(pendingTx.stx.tx.hash)
134+
})
135+
}
136+
128137
implicit val eth_getTransactionByHash =
129138
new JsonDecoder[GetTransactionByHashRequest] with JsonEncoder[GetTransactionByHashResponse] {
130139
override def decodeJson(params: Option[JArray]): Either[JsonRpcError, GetTransactionByHashRequest] =

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

+16-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import io.iohk.ethereum.rlp.RLPImplicits._
2424
import io.iohk.ethereum.rlp.RLPList
2525
import io.iohk.ethereum.rlp.UInt256RLPImplicits._
2626
import io.iohk.ethereum.transactions.PendingTransactionsManager
27-
import io.iohk.ethereum.transactions.PendingTransactionsManager.PendingTransactionsResponse
27+
import io.iohk.ethereum.transactions.PendingTransactionsManager.{PendingTransaction, PendingTransactionsResponse}
2828
import io.iohk.ethereum.utils._
2929
import org.bouncycastle.util.encoders.Hex
3030

@@ -191,6 +191,9 @@ object EthService {
191191

192192
case class GetStorageRootRequest(address: Address, block: BlockParam)
193193
case class GetStorageRootResponse(storageRoot: ByteString)
194+
195+
case class EthPendingTransactionsRequest()
196+
case class EthPendingTransactionsResponse(pendingTransactions: Seq[PendingTransaction])
194197
}
195198

196199
class EthService(
@@ -573,8 +576,8 @@ class EthService(
573576
}
574577
})(Future.successful(OmmersPool.Ommers(Nil))) // NOTE If not Ethash consensus, ommers do not make sense, so => Nil
575578

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

580583
(pendingTransactionsManager ? PendingTransactionsManager.GetPendingTransactions)
@@ -972,4 +975,14 @@ class EthService(
972975
}
973976
}
974977

978+
/**
979+
* Returns the transactions that are pending in the transaction pool and have a from address that is one of the accounts this node manages.
980+
*
981+
* @param req request
982+
* @return pending transactions
983+
*/
984+
def ethPendingTransactions(req: EthPendingTransactionsRequest): ServiceResponse[EthPendingTransactionsResponse] =
985+
getTransactionsFromPool().map { resp =>
986+
Right(EthPendingTransactionsResponse(resp.pendingTransactions))
987+
}
975988
}

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

+2-4
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
@@ -278,6 +277,8 @@ class JsonRpcController(
278277
ethService.getRawTransactionByBlockNumberAndIndex,
279278
req
280279
)
280+
case req @ JsonRpcRequest(_, "eth_pendingTransactions", _, _) =>
281+
handle[EthPendingTransactionsRequest, EthPendingTransactionsResponse](ethService.ethPendingTransactions, req)
281282
}
282283

283284
private def handleDebugRequest: PartialFunction[JsonRpcRequest, Future[JsonRpcResponse]] = {
@@ -349,9 +350,6 @@ class JsonRpcController(
349350
private def handleQARequest: PartialFunction[JsonRpcRequest, Future[JsonRpcResponse]] = {
350351
case req @ JsonRpcRequest(_, "qa_mineBlocks", _, _) =>
351352
handle[QAService.MineBlocksRequest, QAService.MineBlocksResponse](qaService.mineBlocks, req)
352-
353-
case req @ JsonRpcRequest(_, "qa_getPendingTransactions", _, _) =>
354-
handle[GetPendingTransactionsRequest, GetPendingTransactionsResponse](qaService.getPendingTransactions, req)
355353
}
356354

357355
private def handleCheckpointingRequest: PartialFunction[JsonRpcRequest, Future[JsonRpcResponse]] = {

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

+1-13
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

+3-24
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,24 @@
11
package io.iohk.ethereum.jsonrpc
22

3-
import akka.actor.ActorRef
43
import akka.util.ByteString
54
import cats.implicits._
65
import enumeratum._
76
import io.iohk.ethereum.consensus._
87
import io.iohk.ethereum.consensus.ethash.MinerResponses._
98
import io.iohk.ethereum.consensus.ethash.MockedMinerProtocol.MineBlocks
10-
import io.iohk.ethereum.consensus.ethash.{MinerResponse, MinerResponses, TransactionPicker}
9+
import io.iohk.ethereum.consensus.ethash.{MinerResponse, MinerResponses}
1110
import io.iohk.ethereum.jsonrpc.QAService.MineBlocksResponse.MinerResponseType
1211
import io.iohk.ethereum.jsonrpc.QAService.{
13-
GetPendingTransactionsRequest,
14-
GetPendingTransactionsResponse,
1512
MineBlocksRequest,
1613
MineBlocksResponse
1714
}
18-
import io.iohk.ethereum.transactions.PendingTransactionsManager.PendingTransaction
1915
import io.iohk.ethereum.utils.Logger
2016
import monix.execution.Scheduler.Implicits.global
2117
import mouse.all._
22-
import scala.concurrent.duration.FiniteDuration
2318

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

3123
/**
3224
* qa_mineBlocks that instructs mocked miner to mine given number of blocks
@@ -44,16 +36,6 @@ class QAService(
4436
Left(JsonRpcErrors.InternalError)
4537
}
4638
}
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-
}
5739
}
5840

5941
object QAService {
@@ -88,7 +70,4 @@ object QAService {
8870
}
8971
}
9072
}
91-
92-
case class GetPendingTransactionsRequest()
93-
case class GetPendingTransactionsResponse(pendingTransactions: Seq[PendingTransaction])
9473
}

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

+1-6
Original file line numberDiff line numberDiff line change
@@ -366,12 +366,7 @@ trait PersonalServiceBuilder {
366366
trait QaServiceBuilder {
367367
self: ConsensusBuilder with PendingTransactionsManagerBuilder with TxPoolConfigBuilder =>
368368

369-
lazy val qaService =
370-
new QAService(
371-
consensus,
372-
pendingTransactionsManager,
373-
txPoolConfig.getTransactionFromPoolTimeout
374-
)
369+
lazy val qaService = new QAService(consensus)
375370
}
376371

377372
trait CheckpointingServiceBuilder {

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

+47-1
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 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 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 PendingTransactionsResponse(Nil)
1147+
}
1148+
11031149
// NOTE TestSetup uses Ethash consensus; check `consensusConfig`.
11041150
trait TestSetup extends MockFactory with EphemBlockchainTestSetup {
11051151
val blockGenerator = mock[EthashBlockGenerator]

0 commit comments

Comments
 (0)