Coverage Summary for Class: EthModuleTransactionInstant (co.rsk.rpc.modules.eth)
Class |
Class, %
|
Method, %
|
Line, %
|
EthModuleTransactionInstant |
0%
(0/1)
|
0%
(0/5)
|
0%
(0/32)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2018 RSK Labs Ltd.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package co.rsk.rpc.modules.eth;
20
21 import co.rsk.core.Wallet;
22 import co.rsk.core.bc.BlockExecutor;
23 import co.rsk.crypto.Keccak256;
24 import co.rsk.mine.MinerClient;
25 import co.rsk.mine.MinerServer;
26 import co.rsk.net.TransactionGateway;
27 import org.ethereum.config.Constants;
28 import org.ethereum.core.Blockchain;
29 import org.ethereum.core.TransactionPool;
30 import org.ethereum.db.TransactionInfo;
31 import org.ethereum.rpc.TypeConverter;
32 import org.ethereum.rpc.Web3;
33 import org.ethereum.rpc.exception.RskJsonRpcRequestException;
34 import org.ethereum.vm.program.ProgramResult;
35
36 import java.util.Optional;
37
38 import static org.ethereum.rpc.exception.RskJsonRpcRequestException.transactionRevertedExecutionError;
39 import static org.ethereum.rpc.exception.RskJsonRpcRequestException.unknownError;
40
41 public class EthModuleTransactionInstant extends EthModuleTransactionBase {
42
43 private final MinerServer minerServer;
44 private final MinerClient minerClient;
45 private final Blockchain blockchain;
46 private final BlockExecutor blockExecutor;
47
48 public EthModuleTransactionInstant(
49 Constants constants,
50 Wallet wallet,
51 TransactionPool transactionPool,
52 MinerServer minerServer,
53 MinerClient minerClient,
54 Blockchain blockchain,
55 TransactionGateway transactionGateway,
56 BlockExecutor blockExecutor) {
57 super(constants, wallet, transactionPool, transactionGateway);
58
59 this.minerServer = minerServer;
60 this.minerClient = minerClient;
61 this.blockchain = blockchain;
62 this.blockExecutor = blockExecutor;
63 }
64
65 @Override
66 public synchronized String sendTransaction(Web3.CallArguments args) {
67 try {
68 this.blockExecutor.setRegisterProgramResults(true);
69
70 String txHash = super.sendTransaction(args);
71
72 mineTransaction();
73
74 return getReturnMessage(txHash);
75 }
76 finally {
77 this.blockExecutor.setRegisterProgramResults(false);
78 }
79 }
80
81 @Override
82 public String sendRawTransaction(String rawData) {
83 try {
84 this.blockExecutor.setRegisterProgramResults(true);
85
86 String txHash = super.sendRawTransaction(rawData);
87
88 mineTransaction();
89
90 return getReturnMessage(txHash);
91 }
92 finally {
93 this.blockExecutor.setRegisterProgramResults(false);
94 }
95 }
96
97 private void mineTransaction() {
98 minerServer.buildBlockToMine(false);
99 minerClient.mineBlock();
100 }
101
102 /**
103 * When insta-mining we can query the transaction status and return an error response immediately like Ganache.
104 * This does not apply during regular operation because queued transactions are not immediately executed.
105 */
106 private String getReturnMessage(String txHash) {
107 TransactionInfo transactionInfo = blockchain.getTransactionInfo(TypeConverter.stringHexToByteArray(txHash));
108 if (transactionInfo == null) {
109 throw unknownError("Unknown error when sending transaction: transaction wasn't mined");
110 }
111
112 Keccak256 hash = new Keccak256(txHash.substring(2));
113 ProgramResult programResult = this.blockExecutor.getProgramResult(hash);
114
115 if (programResult != null && programResult.isRevert()) {
116 Optional<String> revertReason = EthModule.decodeRevertReason(programResult);
117
118 if (revertReason.isPresent()) {
119 throw RskJsonRpcRequestException.transactionRevertedExecutionError(revertReason.get());
120 } else {
121 throw RskJsonRpcRequestException.transactionRevertedExecutionError();
122 }
123 }
124
125 if (!transactionInfo.getReceipt().isSuccessful()) {
126 throw transactionRevertedExecutionError();
127 }
128
129 return txHash;
130 }
131 }