Coverage Summary for Class: BlockTxsValidationRule (co.rsk.validators)

Class Class, % Method, % Line, %
BlockTxsValidationRule 100% (1/1) 100% (3/3) 67.6% (23/34)


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.RskAddress; 22 import co.rsk.db.RepositoryLocator; 23 import co.rsk.db.RepositorySnapshot; 24 import co.rsk.panic.PanicProcessor; 25 import org.ethereum.core.Block; 26 import org.ethereum.core.Transaction; 27 import org.slf4j.Logger; 28 import org.slf4j.LoggerFactory; 29  30 import java.math.BigInteger; 31 import java.util.HashMap; 32 import java.util.List; 33 import java.util.Map; 34  35 import static java.math.BigInteger.ONE; 36  37 /** 38  * Validate a transactions list. 39  * It validates each transaction nonce againts the expeced sender account nonce 40  * It allows many transactions with the same sender 41  * 42  * @return true if the transactions are valid, false if any transaction is invalid 43  */ 44 public class BlockTxsValidationRule implements BlockParentDependantValidationRule{ 45  46  private static final Logger logger = LoggerFactory.getLogger("blockvalidator"); 47  private static final PanicProcessor panicProcessor = new PanicProcessor(); 48  49  private final RepositoryLocator repositoryLocator; 50  51  public BlockTxsValidationRule(RepositoryLocator repositoryLocator) { 52  this.repositoryLocator = repositoryLocator; 53  } 54  55  @Override 56  public boolean isValid(Block block, Block parent) { 57  58  if(block == null || parent == null) { 59  logger.warn("BlockTxsValidationRule - block or parent are null"); 60  return false; 61  } 62  63  List<Transaction> txs = block.getTransactionsList(); 64  if (txs.isEmpty()) { 65  return true; 66  } 67  68  RepositorySnapshot parentRepo = repositoryLocator.snapshotAt(parent.getHeader()); 69  70  Map<RskAddress, BigInteger> curNonce = new HashMap<>(); 71  72  for (Transaction tx : txs) { 73  try { 74  tx.verify(); 75  } catch (RuntimeException e) { 76  logger.warn("Unable to verify transaction", e); 77  return false; 78  } 79  80  RskAddress sender = tx.getSender(); 81  BigInteger expectedNonce = curNonce.get(sender); 82  if (expectedNonce == null) { 83  expectedNonce = parentRepo.getNonce(sender); 84  } 85  curNonce.put(sender, expectedNonce.add(ONE)); 86  BigInteger txNonce = new BigInteger(1, tx.getNonce()); 87  88  if (!expectedNonce.equals(txNonce)) { 89  logger.warn("Invalid transaction: Tx nonce {} != expected nonce {} (parent nonce: {}): {}", 90  txNonce, expectedNonce, parentRepo.getNonce(sender), tx); 91  92  panicProcessor.panic("invalidtransaction", 93  String.format("Invalid transaction: Tx nonce %s != expected nonce %s (parent nonce: %s): %s", 94  txNonce, expectedNonce, parentRepo.getNonce(sender), tx.getHash())); 95  96  return false; 97  } 98  } 99  100  return true; 101  } 102 }