Coverage Summary for Class: BlockUtils (co.rsk.core.bc)
Class |
Class, %
|
Method, %
|
Line, %
|
BlockUtils |
100%
(1/1)
|
10%
(1/10)
|
2.4%
(1/41)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2017 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.core.bc;
20
21 import co.rsk.crypto.Keccak256;
22 import co.rsk.net.NetBlockStore;
23 import org.ethereum.core.Block;
24 import org.ethereum.core.BlockHeader;
25 import org.ethereum.core.Blockchain;
26 import org.ethereum.db.BlockInformation;
27
28 import java.util.*;
29 import java.util.stream.Collectors;
30
31 /**
32 * Created by ajlopez on 19/08/2016.
33 */
34 public class BlockUtils {
35 private static final long MAX_BLOCK_PROCESS_TIME_NANOSECONDS = 60_000_000_000L;
36
37 private BlockUtils() { }
38
39 public static boolean tooMuchProcessTime(long nanoseconds) {
40 return nanoseconds > MAX_BLOCK_PROCESS_TIME_NANOSECONDS;
41 }
42
43 public static boolean blockInSomeBlockChain(Block block, Blockchain blockChain) {
44 return blockInSomeBlockChain(block.getHash(), block.getNumber(), blockChain);
45 }
46
47 private static boolean blockInSomeBlockChain(Keccak256 blockHash, long blockNumber, Blockchain blockChain) {
48 final List<BlockInformation> blockInformations = blockChain.getBlocksInformationByNumber(blockNumber);
49 return blockInformations.stream().anyMatch(bi -> Arrays.equals(blockHash.getBytes(), bi.getHash()));
50 }
51
52 public static Set<Keccak256> unknownDirectAncestorsHashes(Block block, Blockchain blockChain, NetBlockStore store) {
53 Set<Keccak256> hashes = Collections.singleton(block.getParentHash());
54 return unknownAncestorsHashes(hashes, blockChain, store, false);
55 }
56
57 public static Set<Keccak256> unknownAncestorsHashes(Keccak256 blockHash, Blockchain blockChain, NetBlockStore store) {
58 Set<Keccak256> hashes = Collections.singleton(blockHash);
59 return unknownAncestorsHashes(hashes, blockChain, store, true);
60 }
61
62 public static Set<Keccak256> unknownAncestorsHashes(Set<Keccak256> hashesToProcess, Blockchain blockChain, NetBlockStore store, boolean withUncles) {
63 Set<Keccak256> unknown = new HashSet<>();
64 Set<Keccak256> hashes = hashesToProcess;
65
66 while (!hashes.isEmpty()) {
67 hashes = getNextHashes(hashes, unknown, blockChain, store, withUncles);
68 }
69
70 return unknown;
71 }
72
73 private static Set<Keccak256> getNextHashes(Set<Keccak256> previousHashes, Set<Keccak256> unknown, Blockchain blockChain, NetBlockStore store, boolean withUncles) {
74 Set<Keccak256> nextHashes = new HashSet<>();
75 for (Keccak256 hash : previousHashes) {
76 if (unknown.contains(hash)) {
77 continue;
78 }
79
80 Block block = blockChain.getBlockByHash(hash.getBytes());
81 if (block == null) {
82 block = store.getBlockByHash(hash.getBytes());
83 }
84
85 if (block == null) {
86 unknown.add(hash);
87 continue;
88 }
89
90 if (!block.isGenesis() && !blockInSomeBlockChain(block, blockChain)) {
91 nextHashes.add(block.getParentHash());
92
93 if (withUncles) {
94 for (BlockHeader uncleHeader : block.getUncleList()) {
95 nextHashes.add(uncleHeader.getHash());
96 }
97 }
98 }
99 }
100 return nextHashes;
101 }
102
103 public static void addBlockToList(List<Block> blocks, Block block) {
104 for (Block b : blocks) {
105 if (b.getHash().equals(block.getHash())) {
106 return;
107 }
108 }
109
110 blocks.add(block);
111 }
112
113 public static List<Block> sortBlocksByNumber(List<Block> blocks) {
114 return blocks.stream()
115 .sorted(Comparator.comparingLong(Block::getNumber))
116 .collect(Collectors.toList());
117 }
118
119 }