Coverage Summary for Class: ReceiptStoreImpl (org.ethereum.db)
Class |
Class, %
|
Method, %
|
Line, %
|
ReceiptStoreImpl |
100%
(1/1)
|
75%
(6/8)
|
84.6%
(44/52)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2017 RSK Labs Ltd.
4 * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 package org.ethereum.db;
21
22 import co.rsk.crypto.Keccak256;
23 import org.ethereum.core.Block;
24 import org.ethereum.core.TransactionReceipt;
25 import org.ethereum.datasource.KeyValueDataSource;
26 import org.ethereum.util.RLP;
27 import org.ethereum.util.RLPList;
28
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.List;
32 import java.util.Optional;
33
34 /**
35 * Created by Ruben on 6/1/2016.
36 * Class used to store transaction receipts
37 */
38
39 public class ReceiptStoreImpl implements ReceiptStore {
40 private KeyValueDataSource receiptsDS;
41
42 public ReceiptStoreImpl(KeyValueDataSource receiptsDS){
43 this.receiptsDS = receiptsDS;
44 }
45
46 @Override
47 public void add(byte[] blockHash, int transactionIndex, TransactionReceipt receipt){
48 byte[] txHash = receipt.getTransaction().getHash().getBytes();
49
50 TransactionInfo newTxInfo = new TransactionInfo(receipt, blockHash, transactionIndex);
51
52 List<TransactionInfo> txsInfo = getAll(txHash);
53
54 txsInfo.add(newTxInfo);
55
56 List<byte[]> encodedTxs = new ArrayList<>();
57
58 for (TransactionInfo ti : txsInfo) {
59 encodedTxs.add(ti.getEncoded());
60 }
61
62 byte[][] txsBytes = encodedTxs.toArray(new byte[encodedTxs.size()][]);
63
64 receiptsDS.put(receipt.getTransaction().getHash().getBytes(), RLP.encodeList(txsBytes));
65 }
66
67 @Override
68 public TransactionInfo get(byte[] transactionHash){
69 List<TransactionInfo> txs = getAll(transactionHash);
70
71 if (txs.isEmpty()) {
72 return null;
73 }
74
75 return txs.get(txs.size() - 1);
76 }
77
78 @Override
79 public Optional<TransactionInfo> get(Keccak256 transactionHash, Keccak256 blockHash) {
80 // it is not guaranteed that there will be only one matching TransactionInfo, but if there were more than one,
81 // they would be exactly the same
82 return getAll(transactionHash.getBytes()).stream()
83 .filter(ti -> Arrays.equals(ti.getBlockHash(), blockHash.getBytes()))
84 .findAny();
85 }
86
87 @Override
88 public TransactionInfo getInMainChain(byte[] transactionHash, BlockStore store) {
89 List<TransactionInfo> tis = this.getAll(transactionHash);
90
91 if (tis.isEmpty()) {
92 return null;
93 }
94
95 for (TransactionInfo ti : tis) {
96 byte[] bhash = ti.getBlockHash();
97
98 Block block = store.getBlockByHash(bhash);
99
100 if (block == null) {
101 continue;
102 }
103
104 Block mblock = store.getChainBlockByNumber(block.getNumber());
105
106 if (mblock == null) {
107 continue;
108 }
109
110 if (Arrays.equals(bhash, mblock.getHash().getBytes())) {
111 return ti;
112 }
113 }
114
115 return null;
116 }
117
118 @Override
119 public List<TransactionInfo> getAll(byte[] transactionHash) {
120 byte[] txsBytes = receiptsDS.get(transactionHash);
121
122 if (txsBytes == null || txsBytes.length == 0) {
123 return new ArrayList<TransactionInfo>();
124 }
125
126 List<TransactionInfo> txsInfo = new ArrayList<>();
127 RLPList txsList = (RLPList) RLP.decode2(txsBytes).get(0);
128
129 for (int i = 0; i < txsList.size(); ++i) {
130 RLPList rlpData = ((RLPList) txsList.get(i));
131 txsInfo.add(new TransactionInfo(rlpData.getRLPData()));
132 }
133
134 return txsInfo;
135 }
136
137 @Override
138 public void saveMultiple(byte[] blockHash, List<TransactionReceipt> receipts) {
139 int i = 0;
140 for (TransactionReceipt receipt : receipts) {
141 this.add(blockHash, i++, receipt);
142 }
143 }
144
145 @Override
146 public void flush() {
147 this.receiptsDS.flush();
148 }
149 }