Coverage Summary for Class: Block (org.ethereum.core)
Class |
Method, %
|
Line, %
|
Block |
86.5%
(45/52)
|
67.9%
(93/137)
|
Block$MockitoMock$898112400 |
Block$MockitoMock$898112400$auxiliary$0ASewLdK |
Block$MockitoMock$898112400$auxiliary$0RxrWd66 |
Block$MockitoMock$898112400$auxiliary$2Z7ZK1Kz |
Block$MockitoMock$898112400$auxiliary$4cpNyObd |
Block$MockitoMock$898112400$auxiliary$5DPf0yFj |
Block$MockitoMock$898112400$auxiliary$5ulECbxw |
Block$MockitoMock$898112400$auxiliary$C5HNm6uN |
Block$MockitoMock$898112400$auxiliary$CatoTNB7 |
Block$MockitoMock$898112400$auxiliary$cd3ux9bA |
Block$MockitoMock$898112400$auxiliary$dpQxpOTT |
Block$MockitoMock$898112400$auxiliary$DsaiBxc7 |
Block$MockitoMock$898112400$auxiliary$Dscv1uVP |
Block$MockitoMock$898112400$auxiliary$DUrSbZf0 |
Block$MockitoMock$898112400$auxiliary$E0x2eb9e |
Block$MockitoMock$898112400$auxiliary$eleV1JBH |
Block$MockitoMock$898112400$auxiliary$F60Pgd2y |
Block$MockitoMock$898112400$auxiliary$FD2mvT4o |
Block$MockitoMock$898112400$auxiliary$fgIXTmD9 |
Block$MockitoMock$898112400$auxiliary$GRijBFMY |
Block$MockitoMock$898112400$auxiliary$HmR2gJkl |
Block$MockitoMock$898112400$auxiliary$jF3qKgt1 |
Block$MockitoMock$898112400$auxiliary$koXcF8uw |
Block$MockitoMock$898112400$auxiliary$Ld6ItqFN |
Block$MockitoMock$898112400$auxiliary$Letz41L1 |
Block$MockitoMock$898112400$auxiliary$LsDGuJhu |
Block$MockitoMock$898112400$auxiliary$MyELbnB6 |
Block$MockitoMock$898112400$auxiliary$N0KYuP8O |
Block$MockitoMock$898112400$auxiliary$nUqLBsj0 |
Block$MockitoMock$898112400$auxiliary$p0sr49vt |
Block$MockitoMock$898112400$auxiliary$pELRHB8k |
Block$MockitoMock$898112400$auxiliary$pRkQLFWo |
Block$MockitoMock$898112400$auxiliary$pRN7Rfxd |
Block$MockitoMock$898112400$auxiliary$Qd6YRNZO |
Block$MockitoMock$898112400$auxiliary$rLIJ6Ejo |
Block$MockitoMock$898112400$auxiliary$rzAoSGfH |
Block$MockitoMock$898112400$auxiliary$SUgYT48K |
Block$MockitoMock$898112400$auxiliary$TRyy0bNT |
Block$MockitoMock$898112400$auxiliary$ttpMdcdn |
Block$MockitoMock$898112400$auxiliary$v2oBk1BX |
Block$MockitoMock$898112400$auxiliary$v4flT9hg |
Block$MockitoMock$898112400$auxiliary$V4zhidu6 |
Block$MockitoMock$898112400$auxiliary$w3OmstiE |
Block$MockitoMock$898112400$auxiliary$wcKUN68Q |
Block$MockitoMock$898112400$auxiliary$zh8yFk8F |
Block$MockitoMock$898112400$auxiliary$zZtZrbN1 |
Total |
86.5%
(45/52)
|
67.9%
(93/137)
|
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.core;
21
22 import co.rsk.core.BlockDifficulty;
23 import co.rsk.core.Coin;
24 import co.rsk.core.RskAddress;
25 import co.rsk.core.bc.BlockHashesHelper;
26 import co.rsk.crypto.Keccak256;
27 import co.rsk.panic.PanicProcessor;
28 import com.google.common.collect.ImmutableList;
29 import org.bouncycastle.util.Arrays;
30 import org.bouncycastle.util.BigIntegers;
31 import org.ethereum.util.ByteUtil;
32 import org.ethereum.util.RLP;
33
34 import javax.annotation.Nonnull;
35 import java.math.BigInteger;
36 import java.util.ArrayList;
37 import java.util.Collections;
38 import java.util.List;
39
40 /**
41 * The block in Ethereum is the collection of relevant pieces of information
42 * (known as the blockheader), H, together with information corresponding to
43 * the comprised transactions, R, and a set of other blockheaders U that are known
44 * to have a parent equalBytes to the present block’s parent’s parent
45 * (such blocks are known as uncles).
46 *
47 * @author Roman Mandeleil
48 * @author Nick Savers
49 * @since 20.05.2014
50 */
51 public class Block {
52 private static final PanicProcessor panicProcessor = new PanicProcessor();
53
54 private BlockHeader header;
55
56 private List<Transaction> transactionsList;
57
58 private List<BlockHeader> uncleList;
59
60 /* Private */
61 private byte[] rlpEncoded;
62
63 /* Indicates if this block can or cannot be changed */
64 private volatile boolean sealed;
65
66 public static Block createBlockFromHeader(BlockHeader header, boolean isRskip126Enabled) {
67 return new Block(header, Collections.emptyList(), Collections.emptyList(), isRskip126Enabled, true, false);
68 }
69
70 public Block(BlockHeader header, List<Transaction> transactionsList, List<BlockHeader> uncleList, boolean isRskip126Enabled, boolean sealed) {
71 this(header, transactionsList, uncleList, isRskip126Enabled, sealed, true);
72 }
73
74 private Block(BlockHeader header, List<Transaction> transactionsList, List<BlockHeader> uncleList, boolean isRskip126Enabled, boolean sealed, boolean checktxs) {
75 byte[] calculatedRoot = BlockHashesHelper.getTxTrieRoot(transactionsList, isRskip126Enabled);
76
77 if (checktxs && !Arrays.areEqual(header.getTxTrieRoot(), calculatedRoot)) {
78 String message = String.format(
79 "Transactions trie root validation failed for block %d %s", header.getNumber(), header.getHash()
80 );
81 panicProcessor.panic("txroot", message);
82 throw new IllegalArgumentException(message);
83 }
84
85 this.header = header;
86 this.transactionsList = ImmutableList.copyOf(transactionsList);
87 this.uncleList = ImmutableList.copyOf(uncleList);
88 this.sealed = sealed;
89 }
90
91 public void seal() {
92 this.sealed = true;
93 this.header.seal();
94 }
95
96 public boolean isSealed() {
97 return this.sealed;
98 }
99
100 // TODO(mc) remove this method and create a new ExecutedBlock class or similar
101 public void setTransactionsList(@Nonnull List<Transaction> transactionsList) {
102 /* A sealed block is immutable, cannot be changed */
103 if (this.sealed) {
104 throw new SealedBlockException("trying to alter transaction list");
105 }
106
107 this.transactionsList = Collections.unmodifiableList(transactionsList);
108 rlpEncoded = null;
109 }
110
111 public BlockHeader getHeader() {
112 return this.header;
113 }
114
115 public Keccak256 getHash() {
116 return this.header.getHash();
117 }
118
119 public Keccak256 getParentHash() {
120 return this.header.getParentHash();
121 }
122
123 public byte[] getUnclesHash() {
124 return this.header.getUnclesHash();
125 }
126
127 public RskAddress getCoinbase() {
128 return this.header.getCoinbase();
129 }
130
131 public byte[] getStateRoot() {
132 return this.header.getStateRoot();
133 }
134
135 public void setStateRoot(byte[] stateRoot) {
136 /* A sealed block is immutable, cannot be changed */
137 if (this.sealed) {
138 throw new SealedBlockException("trying to alter state root");
139 }
140
141 this.header.setStateRoot(stateRoot);
142 }
143
144 public byte[] getTxTrieRoot() {
145 return this.header.getTxTrieRoot();
146 }
147
148 public byte[] getReceiptsRoot() {
149 return this.header.getReceiptsRoot();
150 }
151
152 public byte[] getLogBloom() {
153 return this.header.getLogsBloom();
154 }
155
156 public BlockDifficulty getDifficulty() {
157 return this.header.getDifficulty();
158 }
159
160 public Coin getFeesPaidToMiner() {
161 return this.header.getPaidFees();
162 }
163
164 public BlockDifficulty getCumulativeDifficulty() {
165 BlockDifficulty calcDifficulty = this.header.getDifficulty();
166 for (BlockHeader uncle : uncleList) {
167 calcDifficulty = calcDifficulty.add(uncle.getDifficulty());
168 }
169 return calcDifficulty;
170 }
171
172 public long getTimestamp() {
173 return this.header.getTimestamp();
174 }
175
176 public long getNumber() {
177 return this.header.getNumber();
178 }
179
180 public byte[] getGasLimit() {
181 return this.header.getGasLimit();
182 }
183
184 public long getGasUsed() {
185 return this.header.getGasUsed();
186 }
187
188 public byte[] getExtraData() {
189 return this.header.getExtraData();
190 }
191
192 public List<Transaction> getTransactionsList() {
193 return this.transactionsList;
194 }
195
196 public List<BlockHeader> getUncleList() {
197 return this.uncleList;
198 }
199
200 public Coin getMinimumGasPrice() {
201 return this.header.getMinimumGasPrice();
202 }
203
204 // [parent_hash, uncles_hash, coinbase, state_root, tx_trie_root,
205 // difficulty, number, minGasPrice, gasLimit, gasUsed, timestamp,
206 // extradata, nonce]
207
208 @Override
209 public String toString() {
210 StringBuilder toStringBuff = new StringBuilder();
211 toStringBuff.append(ByteUtil.toHexString(this.getEncoded())).append("\n");
212 toStringBuff.append("BlockData [ ");
213 toStringBuff.append("hash=").append(this.getHash()).append("\n");
214 toStringBuff.append(header.toString());
215
216 if (!getUncleList().isEmpty()) {
217 toStringBuff.append("Uncles [\n");
218 for (BlockHeader uncle : getUncleList()) {
219 toStringBuff.append(uncle.toString());
220 toStringBuff.append("\n");
221 }
222 toStringBuff.append("]\n");
223 } else {
224 toStringBuff.append("Uncles []\n");
225 }
226 if (!getTransactionsList().isEmpty()) {
227 toStringBuff.append("Txs [\n");
228 for (Transaction tx : getTransactionsList()) {
229 toStringBuff.append(tx);
230 toStringBuff.append("\n");
231 }
232 toStringBuff.append("]\n");
233 } else {
234 toStringBuff.append("Txs []\n");
235 }
236 toStringBuff.append("]");
237
238 return toStringBuff.toString();
239 }
240
241 /**
242 * check if param block is son of this block
243 *
244 * @param block - possible a son of this
245 * @return - true if this block is parent of param block
246 */
247 public boolean isParentOf(Block block) {
248 return this.header.isParentOf(block.getHeader());
249 }
250
251 public boolean isGenesis() {
252 return this.header.isGenesis();
253 }
254
255 public boolean isEqual(Block block) {
256 return this.getHash().equals(block.getHash());
257 }
258
259 public boolean fastEquals(Block block) {
260 return block != null && this.getHash().equals(block.getHash());
261 }
262
263 private byte[] getTransactionsEncoded() {
264 byte[][] transactionsEncoded = new byte[transactionsList.size()][];
265 int i = 0;
266 for (Transaction tx : transactionsList) {
267 transactionsEncoded[i] = tx.getEncoded();
268 ++i;
269 }
270 return RLP.encodeList(transactionsEncoded);
271 }
272
273 private byte[] getUnclesEncoded() {
274 byte[][] unclesEncoded = new byte[uncleList.size()][];
275 int i = 0;
276 for (BlockHeader uncle : uncleList) {
277 unclesEncoded[i] = uncle.getFullEncoded();
278 ++i;
279 }
280 return RLP.encodeList(unclesEncoded);
281 }
282
283 public byte[] getEncoded() {
284 if (rlpEncoded == null) {
285 byte[] header = this.header.getFullEncoded();
286
287 List<byte[]> block = getBodyElements();
288 block.add(0, header);
289 byte[][] elements = block.toArray(new byte[block.size()][]);
290
291 this.rlpEncoded = RLP.encodeList(elements);
292 }
293
294 return rlpEncoded;
295 }
296
297 private List<byte[]> getBodyElements() {
298 byte[] transactions = getTransactionsEncoded();
299 byte[] uncles = getUnclesEncoded();
300
301 List<byte[]> body = new ArrayList<>();
302 body.add(transactions);
303 body.add(uncles);
304
305 return body;
306 }
307
308 public String getPrintableHash() {
309 return header.getPrintableHash();
310 }
311
312 private String getParentPrintableHash() {
313 return header.getParentPrintableHash();
314 }
315
316 public String getPrintableHashForMergedMining() {
317 return this.header.getPrintableHashForMergedMining();
318 }
319
320 public byte[] getHashForMergedMining() {
321 return this.header.getHashForMergedMining();
322 }
323
324 public String getShortDescr() {
325 return "#" + getNumber() + " (" + getPrintableHash() + " <~ "
326 + getParentPrintableHash() + ") Txs:" + getTransactionsList().size() +
327 ", Unc: " + getUncleList().size();
328 }
329
330 public String getHashJsonString() {
331 return getHash().toJsonString();
332 }
333
334 public String getParentHashJsonString() {
335 return getParentHash().toJsonString();
336 }
337
338 public byte[] getBitcoinMergedMiningHeader() {
339 return this.header.getBitcoinMergedMiningHeader();
340 }
341
342 public void setBitcoinMergedMiningHeader(byte[] bitcoinMergedMiningHeader) {
343 /* A sealed block is immutable, cannot be changed */
344 if (this.sealed) {
345 throw new SealedBlockException("trying to alter bitcoin merged mining header");
346 }
347
348 this.header.setBitcoinMergedMiningHeader(bitcoinMergedMiningHeader);
349 rlpEncoded = null;
350 }
351
352 public byte[] getBitcoinMergedMiningMerkleProof() {
353 return this.header.getBitcoinMergedMiningMerkleProof();
354 }
355
356 public void setBitcoinMergedMiningMerkleProof(byte[] bitcoinMergedMiningMerkleProof) {
357 /* A sealed block is immutable, cannot be changed */
358 if (this.sealed) {
359 throw new SealedBlockException("trying to alter bitcoin merged mining Merkle proof");
360 }
361
362 this.header.setBitcoinMergedMiningMerkleProof(bitcoinMergedMiningMerkleProof);
363 rlpEncoded = null;
364 }
365
366 public byte[] getBitcoinMergedMiningCoinbaseTransaction() {
367 return this.header.getBitcoinMergedMiningCoinbaseTransaction();
368 }
369
370 public void setBitcoinMergedMiningCoinbaseTransaction(byte[] bitcoinMergedMiningCoinbaseTransaction) {
371 if (this.sealed) {
372 throw new SealedBlockException("trying to alter bitcoin merged mining coinbase transaction");
373 }
374
375 this.header.setBitcoinMergedMiningCoinbaseTransaction(bitcoinMergedMiningCoinbaseTransaction);
376 rlpEncoded = null;
377 }
378
379 public BigInteger getGasLimitAsInteger() {
380 return (this.getGasLimit() == null) ? null : BigIntegers.fromUnsignedByteArray(this.getGasLimit());
381 }
382
383 public void flushRLP() {
384 this.rlpEncoded = null;
385 }
386 }