Coverage Summary for Class: ForkDetectionDataRule (co.rsk.validators)
Class |
Class, %
|
Method, %
|
Line, %
|
ForkDetectionDataRule |
0%
(0/1)
|
0%
(0/7)
|
0%
(0/38)
|
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.validators;
20
21 import co.rsk.core.bc.ConsensusValidationMainchainView;
22 import co.rsk.mine.ForkDetectionDataCalculator;
23 import co.rsk.panic.PanicProcessor;
24 import org.ethereum.config.blockchain.upgrades.ActivationConfig;
25 import org.ethereum.config.blockchain.upgrades.ConsensusRule;
26 import org.ethereum.core.Block;
27 import org.ethereum.core.BlockHeader;
28 import org.ethereum.util.ByteUtil;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import java.util.Arrays;
33 import java.util.List;
34
35 /**
36 * Created by martin.medina on 14/05/19.
37 */
38 public class ForkDetectionDataRule implements BlockValidationRule, BlockHeaderValidationRule {
39
40 private static final Logger logger = LoggerFactory.getLogger("blockvalidator");
41 private static final PanicProcessor panicProcessor = new PanicProcessor();
42
43 private static final String PANIC_LOGGING_TOPIC = "invalidForkDetectionDataRule";
44
45 private final ActivationConfig activationConfig;
46 private final ForkDetectionDataCalculator forkDetectionDataCalculator;
47 private final ConsensusValidationMainchainView mainchainView;
48 private final int requiredBlocksForForkDetectionDataCalculation;
49
50 public ForkDetectionDataRule(
51 ActivationConfig activationConfig,
52 ConsensusValidationMainchainView mainchainView,
53 ForkDetectionDataCalculator forkDetectionDataCalculator,
54 int requiredBlocksForForkDetectionDataCalculation) {
55 this.activationConfig = activationConfig;
56 this.mainchainView = mainchainView;
57 this.forkDetectionDataCalculator = forkDetectionDataCalculator;
58 this.requiredBlocksForForkDetectionDataCalculation = requiredBlocksForForkDetectionDataCalculation;
59 }
60
61 @Override
62 public boolean isValid(Block block) {
63 return isValid(block.getHeader());
64 }
65
66 @Override
67 public boolean isValid(BlockHeader header) {
68 if(activationConfig.isActive(ConsensusRule.RSKIP110, header.getNumber()) )
69 {
70 if (hasForkDetectionDataWhereItShouldNotHave(header)){
71 return false;
72 }
73
74 if(requiredBlocksForForkDetectionDataCalculation < header.getNumber()) {
75 List<BlockHeader> headersView = mainchainView.get(
76 header.getParentHash(),
77 requiredBlocksForForkDetectionDataCalculation
78 );
79 if (!hasEnoughBlocksToCalculateForkDetectionData(header, headersView)) {
80 return false;
81 }
82
83 return isForkDetectionDataEqual(header, headersView);
84 }
85 }
86
87 return true;
88 }
89
90 private boolean hasForkDetectionDataWhereItShouldNotHave(BlockHeader header) {
91 if(header.getNumber() < requiredBlocksForForkDetectionDataCalculation
92 && header.getMiningForkDetectionData().length > 0) {
93 logger.warn("Header for block number {} includes fork detection data but it should not.",
94 header.getNumber());
95 panicProcessor.panic(
96 PANIC_LOGGING_TOPIC,
97 "Header includes fork detection data but it should not."
98 );
99 return true;
100 }
101 return false;
102 }
103
104 private boolean isForkDetectionDataEqual(BlockHeader header, List<BlockHeader> headersView) {
105 byte[] expectedForkDetectionData = forkDetectionDataCalculator.calculateWithBlockHeaders(headersView);
106 if (!Arrays.equals(expectedForkDetectionData, header.getMiningForkDetectionData())) {
107 logger.warn("Fork detection data does not match. Expected {} Actual: {}",
108 ByteUtil.toHexStringOrEmpty(expectedForkDetectionData),
109 ByteUtil.toHexStringOrEmpty(header.getMiningForkDetectionData())
110 );
111 panicProcessor.panic(
112 PANIC_LOGGING_TOPIC,
113 "Block hash for merged mining does not match."
114 );
115 return false;
116 }
117
118 return true;
119 }
120
121 private boolean hasEnoughBlocksToCalculateForkDetectionData(BlockHeader header, List<BlockHeader> headersView) {
122 if (headersView.size() != requiredBlocksForForkDetectionDataCalculation) {
123 logger.error("Missing blocks to calculate fork detection data. Block hash {} ", header.getPrintableHash());
124 panicProcessor.panic(
125 PANIC_LOGGING_TOPIC,
126 "Missing blocks to calculate fork detection data."
127 );
128 return false;
129 }
130
131 return true;
132 }
133 }