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 }