Coverage Summary for Class: Web3InformationRetriever (co.rsk.rpc)
Class |
Method, %
|
Line, %
|
Web3InformationRetriever |
71.4%
(5/7)
|
87.5%
(28/32)
|
Web3InformationRetriever$MockitoMock$1399703513 |
Web3InformationRetriever$MockitoMock$1399703513$auxiliary$0q0724Ll |
Web3InformationRetriever$MockitoMock$1399703513$auxiliary$bAmJieOQ |
Web3InformationRetriever$MockitoMock$1399703513$auxiliary$gjH3qiMJ |
Web3InformationRetriever$MockitoMock$1399703513$auxiliary$MnLawO9R |
Web3InformationRetriever$MockitoMock$1399703513$auxiliary$yi5vQiZh |
Total |
71.4%
(5/7)
|
87.5%
(28/32)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2019 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;
20
21 import co.rsk.core.bc.AccountInformationProvider;
22 import co.rsk.db.RepositoryLocator;
23 import org.ethereum.core.Block;
24 import org.ethereum.core.Blockchain;
25 import org.ethereum.core.Transaction;
26 import org.ethereum.core.TransactionPool;
27 import org.ethereum.rpc.exception.RskJsonRpcRequestException;
28
29 import java.util.List;
30 import java.util.Optional;
31
32 import static org.ethereum.rpc.TypeConverter.stringHexToBigInteger;
33 import static org.ethereum.rpc.exception.RskJsonRpcRequestException.*;
34
35 /**
36 * Retrieves information requested by web3 based on the block identifier:
37 * <p>
38 * HEX String - an integer block number
39 * String "earliest" for the earliest/genesis block
40 * String "latest" - for the latest mined block
41 * String "pending" - for the pending state/transactions
42 */
43 public class Web3InformationRetriever {
44 private final TransactionPool transactionPool;
45 private final Blockchain blockchain;
46 private final RepositoryLocator locator;
47
48 private static final String EARLIEST = "earliest";
49 private static final String LATEST = "latest";
50 private static final String PENDING = "pending";
51
52
53 public Web3InformationRetriever(TransactionPool transactionPool, Blockchain blockchain, RepositoryLocator locator) {
54
55 this.transactionPool = transactionPool;
56 this.blockchain = blockchain;
57 this.locator = locator;
58 }
59
60 /**
61 * Retrieves the block based on the identifier.
62 * @param identifier {@link Web3InformationRetriever}
63 * @return An optional containing the block if found.
64 * @throws RskJsonRpcRequestException if the identifier is {@link #PENDING}, as it is not implemented yet.
65 */
66 public Optional<Block> getBlock(String identifier) {
67 if (PENDING.equals(identifier)) {
68 throw unimplemented("This method doesn't support 'pending' as a parameter");
69 }
70
71 Block block;
72 if (LATEST.equals(identifier)) {
73 block = blockchain.getBestBlock();
74 } else if (EARLIEST.equals(identifier)) {
75 block = blockchain.getBlockByNumber(0);
76 } else {
77 block = this.blockchain.getBlockByNumber(getBlockNumber(identifier));
78 }
79
80 return Optional.ofNullable(block);
81 }
82
83 /**
84 * Retrieves an {@link AccountInformationProvider} based on the identifier.
85 * @param identifier {@link Web3InformationRetriever}
86 * @return The {@link AccountInformationProvider}
87 * @throws RskJsonRpcRequestException if the block indicated by the identifier is not found or the state for the
88 * block was not found.
89 */
90 public AccountInformationProvider getInformationProvider(String identifier) {
91 if (PENDING.equals(identifier)) {
92 return transactionPool.getPendingState();
93 }
94
95 Optional<Block> optBlock = getBlock(identifier);
96 if (!optBlock.isPresent()) {
97 throw blockNotFound(String.format("Block %s not found", identifier));
98 }
99
100 Block block = optBlock.get();
101 return locator.findSnapshotAt(block.getHeader()).orElseThrow(() -> RskJsonRpcRequestException
102 .stateNotFound(String.format("State not found for block with hash %s", block.getHash())));
103 }
104
105 /**
106 * Retrieves an list of {@link Transaction} based on the identifier
107 * @param identifier {@link Web3InformationRetriever}
108 * @return The {@link Transaction Transactions} of {@link TransactionPool} if the identifier is {@link #PENDING},
109 * if not, the ones on the specified block.
110 * @throws RskJsonRpcRequestException if the block indicated by the identifier is not foundl.
111 */
112 public List<Transaction> getTransactions(String identifier) {
113 if (PENDING.equals(identifier)) {
114 return transactionPool.getPendingTransactions();
115 }
116
117 Optional<Block> block = getBlock(identifier);
118
119 return block.map(Block::getTransactionsList)
120 .orElseThrow(() ->
121 blockNotFound(String.format("Block %s not found", identifier)));
122
123 }
124
125 private long getBlockNumber(String identifier) {
126 long blockNumber;
127 try {
128 blockNumber = stringHexToBigInteger(identifier).longValue();
129 } catch (NumberFormatException | StringIndexOutOfBoundsException e) {
130 throw invalidParamError(String.format("invalid blocknumber %s", identifier));
131 }
132 return blockNumber;
133 }
134 }