Skip to content

Commit 87aa286

Browse files
committed
Merge remote-tracking branch 'origin/develop' into ETCM-446-connection-limit-ranges
2 parents 69efa13 + a5092d0 commit 87aa286

File tree

5 files changed

+211
-63
lines changed

5 files changed

+211
-63
lines changed

src/main/scala/io/iohk/ethereum/domain/TransactionOutcome.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package io.iohk.ethereum.domain
22

33
import akka.util.ByteString
44

5-
trait TransactionOutcome
5+
sealed trait TransactionOutcome
66

77
case class HashOutcome(stateHash: ByteString) extends TransactionOutcome
88

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

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import io.iohk.ethereum.consensus.blocks.PendingBlockAndState
1111
import io.iohk.ethereum.consensus.ethash.EthashUtils
1212
import io.iohk.ethereum.crypto._
1313
import io.iohk.ethereum.db.storage.TransactionMappingStorage.TransactionLocation
14-
import io.iohk.ethereum.domain.{BlockHeader, SignedTransaction, UInt256, _}
14+
import io.iohk.ethereum.domain.{BlockHeader, SignedTransaction, _}
1515
import io.iohk.ethereum.jsonrpc.AkkaTaskOps._
16-
import io.iohk.ethereum.jsonrpc.FilterManager.{FilterChanges, FilterLogs, LogFilterLogs, TxLog}
16+
import io.iohk.ethereum.jsonrpc.FilterManager.{FilterChanges, FilterLogs, LogFilterLogs}
1717
import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController.JsonRpcConfig
1818
import io.iohk.ethereum.jsonrpc.{FilterManager => FM}
1919
import io.iohk.ethereum.keystore.KeyStore
@@ -24,7 +24,6 @@ import io.iohk.ethereum.rlp
2424
import io.iohk.ethereum.rlp.RLPImplicitConversions._
2525
import io.iohk.ethereum.rlp.RLPImplicits._
2626
import io.iohk.ethereum.rlp.RLPList
27-
import io.iohk.ethereum.rlp.UInt256RLPImplicits._
2827
import io.iohk.ethereum.transactions.PendingTransactionsManager
2928
import io.iohk.ethereum.transactions.PendingTransactionsManager.{PendingTransaction, PendingTransactionsResponse}
3029
import io.iohk.ethereum.utils._
@@ -346,39 +345,22 @@ class EthService(
346345
stx <- body.transactionList.lift(txIndex)
347346
receipts <- blockchain.getReceiptsByHash(blockHash)
348347
receipt: Receipt <- receipts.lift(txIndex)
348+
// another possibility would be to throw an exception and fail hard, as if we cannot calculate sender for transaction
349+
// included in blockchain it means that something is terribly wrong
350+
sender <- SignedTransaction.getSender(stx)
349351
} yield {
350-
// safe to call get as we are geting saved transaction with receipt (sender was proper formed)
351-
val sender = SignedTransaction.getSender(stx)
352-
val contractAddress = if (stx.tx.isContractInit && sender.isDefined) {
353-
//do not subtract 1 from nonce because in transaction we have nonce of account before transaction execution
354-
val hash = kec256(rlp.encode(RLPList(sender.get.bytes, UInt256(stx.tx.nonce).toRLPEncodable)))
355-
Some(Address(hash))
356-
} else {
357-
None
358-
}
352+
353+
val gasUsed =
354+
if (txIndex == 0) receipt.cumulativeGasUsed
355+
else receipt.cumulativeGasUsed - receipts(txIndex - 1).cumulativeGasUsed
359356

360357
TransactionReceiptResponse(
361-
transactionHash = stx.hash,
358+
receipt = receipt,
359+
stx = stx,
360+
signedTransactionSender = sender,
362361
transactionIndex = txIndex,
363-
blockNumber = header.number,
364-
blockHash = header.hash,
365-
cumulativeGasUsed = receipt.cumulativeGasUsed,
366-
gasUsed =
367-
if (txIndex == 0) receipt.cumulativeGasUsed
368-
else receipt.cumulativeGasUsed - receipts(txIndex - 1).cumulativeGasUsed,
369-
contractAddress = contractAddress,
370-
logs = receipt.logs.zipWithIndex.map { case (txLog, index) =>
371-
TxLog(
372-
logIndex = index,
373-
transactionIndex = txIndex,
374-
transactionHash = stx.hash,
375-
blockHash = header.hash,
376-
blockNumber = header.number,
377-
address = txLog.loggerAddress,
378-
data = txLog.data,
379-
topics = txLog.logTopics
380-
)
381-
}
362+
blockHeader = header,
363+
gasUsedByTransaction = gasUsed
382364
)
383365
}
384366

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

33
import akka.util.ByteString
4-
import io.iohk.ethereum.domain.Address
4+
import io.iohk.ethereum.crypto.kec256
5+
import io.iohk.ethereum.domain.{
6+
Address,
7+
BlockHeader,
8+
FailureOutcome,
9+
HashOutcome,
10+
Receipt,
11+
SignedTransaction,
12+
SuccessOutcome,
13+
UInt256
14+
}
515
import io.iohk.ethereum.jsonrpc.FilterManager.TxLog
16+
import io.iohk.ethereum.rlp
17+
import io.iohk.ethereum.rlp.RLPList
18+
import io.iohk.ethereum.rlp.RLPImplicitConversions._
19+
import io.iohk.ethereum.rlp.UInt256RLPImplicits._
620

21+
/**
22+
* Params docs copied from - https://eth.wiki/json-rpc/API
23+
*
24+
* @param transactionHash DATA, 32 Bytes - hash of the transaction.
25+
* @param transactionIndex QUANTITY - integer of the transactions index position in the block.
26+
* @param blockHash DATA, 32 Bytes - hash of the block where this transaction was in.
27+
* @param blockNumber QUANTITY - block number where this transaction was in.
28+
* @param from DATA, 20 Bytes - address of the sender.
29+
* @param to DATA, 20 Bytes - address of the receiver. None when its a contract creation transaction.
30+
* @param cumulativeGasUsed QUANTITY - The total amount of gas used when this transaction was executed in the block.
31+
* @param gasUsed QUANTITY - The amount of gas used by this specific transaction alone.
32+
* @param contractAddress DATA, 20 Bytes - The contract address created, if the transaction was a contract creation, otherwise None.
33+
* @param logs Array - Array of log objects, which this transaction generated.
34+
* @param logsBloom DATA, 256 Bytes - Bloom filter for light clients to quickly retrieve related logs.
35+
* @param root DATA 32 bytes of post-transaction stateroot (pre Byzantium, otherwise None)
36+
* @param status QUANTITY either 1 (success) or 0 (failure) (post Byzantium, otherwise None)
37+
*/
738
case class TransactionReceiptResponse(
839
transactionHash: ByteString,
940
transactionIndex: BigInt,
1041
blockNumber: BigInt,
1142
blockHash: ByteString,
43+
from: Address,
44+
to: Option[Address],
1245
cumulativeGasUsed: BigInt,
1346
gasUsed: BigInt,
1447
contractAddress: Option[Address],
15-
logs: Seq[TxLog]
48+
logs: Seq[TxLog],
49+
logsBloom: ByteString,
50+
root: Option[ByteString],
51+
status: Option[BigInt]
1652
)
53+
54+
object TransactionReceiptResponse {
55+
56+
def apply(
57+
receipt: Receipt,
58+
stx: SignedTransaction,
59+
signedTransactionSender: Address,
60+
transactionIndex: Int,
61+
blockHeader: BlockHeader,
62+
gasUsedByTransaction: BigInt
63+
): TransactionReceiptResponse = {
64+
val contractAddress = if (stx.tx.isContractInit) {
65+
//do not subtract 1 from nonce because in transaction we have nonce of account before transaction execution
66+
val hash = kec256(rlp.encode(RLPList(signedTransactionSender.bytes, UInt256(stx.tx.nonce).toRLPEncodable)))
67+
Some(Address(hash))
68+
} else {
69+
None
70+
}
71+
val txLogs = receipt.logs.zipWithIndex.map { case (txLog, index) =>
72+
TxLog(
73+
logIndex = index,
74+
transactionIndex = transactionIndex,
75+
transactionHash = stx.hash,
76+
blockHash = blockHeader.hash,
77+
blockNumber = blockHeader.number,
78+
address = txLog.loggerAddress,
79+
data = txLog.data,
80+
topics = txLog.logTopics
81+
)
82+
}
83+
84+
val (root, status) = receipt.postTransactionStateHash match {
85+
case FailureOutcome => (None, Some(BigInt(0)))
86+
case SuccessOutcome => (None, Some(BigInt(1)))
87+
case HashOutcome(stateHash) => (Some(stateHash), None)
88+
}
89+
90+
new TransactionReceiptResponse(
91+
transactionHash = stx.hash,
92+
transactionIndex = transactionIndex,
93+
blockNumber = blockHeader.number,
94+
blockHash = blockHeader.hash,
95+
from = signedTransactionSender,
96+
to = stx.tx.receivingAddress,
97+
cumulativeGasUsed = receipt.cumulativeGasUsed,
98+
gasUsed = gasUsedByTransaction,
99+
contractAddress = contractAddress,
100+
logs = txLogs,
101+
logsBloom = receipt.logsBloomFilter,
102+
root = root,
103+
status = status
104+
)
105+
}
106+
}

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

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import akka.actor.ActorSystem
44
import akka.testkit.{TestKit, TestProbe}
55
import akka.util.ByteString
66
import io.iohk.ethereum.Mocks.MockValidatorsAlwaysSucceed
7+
import io.iohk.ethereum._
78
import io.iohk.ethereum.blockchain.sync.SyncProtocol.Status.Progress
89
import io.iohk.ethereum.blockchain.sync.{EphemBlockchainTestSetup, SyncProtocol}
910
import io.iohk.ethereum.consensus._
@@ -15,7 +16,6 @@ import io.iohk.ethereum.db.storage.AppStateStorage
1516
import io.iohk.ethereum.domain.BlockHeader.getEncodedWithoutNonce
1617
import io.iohk.ethereum.domain.{Address, Block, BlockHeader, BlockchainImpl, UInt256, _}
1718
import io.iohk.ethereum.jsonrpc.EthService.{ProtocolVersionRequest, _}
18-
import io.iohk.ethereum.jsonrpc.FilterManager.TxLog
1919
import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController.JsonRpcConfig
2020
import io.iohk.ethereum.keystore.KeyStore
2121
import io.iohk.ethereum.ledger.Ledger.TxResult
@@ -31,7 +31,6 @@ import io.iohk.ethereum.transactions.PendingTransactionsManager.{
3131
PendingTransactionsResponse
3232
}
3333
import io.iohk.ethereum.utils._
34-
import io.iohk.ethereum._
3534
import monix.execution.Scheduler.Implicits.global
3635
import org.bouncycastle.util.encoders.Hex
3736
import org.scalactic.TypeCheckedTripleEquals
@@ -1072,25 +1071,12 @@ class EthServiceSpec
10721071
GetTransactionReceiptResponse(
10731072
Some(
10741073
TransactionReceiptResponse(
1075-
transactionHash = contractCreatingTransaction.hash,
1074+
receipt = fakeReceipt.copy(cumulativeGasUsed = fakeReceipt.cumulativeGasUsed + gasUsedByTx),
1075+
stx = contractCreatingTransaction,
1076+
signedTransactionSender = contractCreatingTransactionSender,
10761077
transactionIndex = 1,
1077-
blockNumber = Fixtures.Blocks.Block3125369.header.number,
1078-
blockHash = Fixtures.Blocks.Block3125369.header.hash,
1079-
cumulativeGasUsed = fakeReceipt.cumulativeGasUsed + gasUsedByTx,
1080-
gasUsed = gasUsedByTx,
1081-
contractAddress = Some(createdContractAddress),
1082-
logs = Seq(
1083-
TxLog(
1084-
logIndex = 0,
1085-
transactionIndex = 1,
1086-
transactionHash = contractCreatingTransaction.hash,
1087-
blockHash = Fixtures.Blocks.Block3125369.header.hash,
1088-
blockNumber = Fixtures.Blocks.Block3125369.header.number,
1089-
address = fakeReceipt.logs.head.loggerAddress,
1090-
data = fakeReceipt.logs.head.data,
1091-
topics = fakeReceipt.logs.head.logTopics
1092-
)
1093-
)
1078+
blockHeader = Fixtures.Blocks.Block3125369.header,
1079+
gasUsedByTransaction = gasUsedByTx
10941080
)
10951081
)
10961082
)
@@ -1301,6 +1287,8 @@ class EthServiceSpec
13011287
0x3d.toByte
13021288
)
13031289

1290+
val contractCreatingTransactionSender = SignedTransaction.getSender(contractCreatingTransaction).get
1291+
13041292
val fakeReceipt = Receipt.withHashOutcome(
13051293
postTransactionStateHash = ByteString(Hex.decode("01" * 32)),
13061294
cumulativeGasUsed = 43,

0 commit comments

Comments
 (0)