Coverage Summary for Class: SnapshotManager (co.rsk.core)

Class Class, % Method, % Line, %
SnapshotManager 0% (0/1) 0% (0/5) 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.core; 20  21 import co.rsk.mine.MinerServer; 22 import com.google.common.annotations.VisibleForTesting; 23 import org.ethereum.core.Block; 24 import org.ethereum.core.Blockchain; 25 import org.ethereum.core.TransactionPool; 26 import org.ethereum.db.BlockStore; 27  28 import java.util.ArrayList; 29 import java.util.List; 30 import java.util.stream.Collectors; 31  32 /** 33  * Created by ajlopez on 15/04/2017. 34  */ 35 public class SnapshotManager { 36  private List<Long> snapshots = new ArrayList<>(); 37  private final Blockchain blockchain; 38  private final BlockStore blockStore; 39  private final TransactionPool transactionPool; 40  private final MinerServer minerServer; 41  42  public SnapshotManager( 43  Blockchain blockchain, 44  BlockStore blockStore, 45  TransactionPool transactionPool, 46  MinerServer minerServer) { 47  this.blockchain = blockchain; 48  this.blockStore = blockStore; 49  this.transactionPool = transactionPool; 50  this.minerServer = minerServer; 51  } 52  53  public int takeSnapshot() { 54  snapshots.add(blockchain.getBestBlock().getNumber()); 55  return this.snapshots.size(); 56  } 57  58  public boolean resetSnapshots() { 59  this.snapshots = new ArrayList<>(); 60  61  long bestNumber = blockchain.getBestBlock().getNumber(); 62  63  Block block = blockStore.getChainBlockByNumber(0); 64  BlockDifficulty difficulty = blockStore.getTotalDifficultyForHash(block.getHash().getBytes()); 65  66  blockchain.setStatus(block, difficulty); 67  68  // To clean pending state, first process the fork 69  transactionPool.processBest(block); 70  // then, clear any reverted transaction 71  transactionPool.removeTransactions(transactionPool.getPendingTransactions()); 72  transactionPool.removeTransactions(transactionPool.getQueuedTransactions()); 73  74  // Remove removed blocks from store 75  for (long nb = blockchain.getBestBlock().getNumber() + 1; nb <= bestNumber; nb++) { 76  blockchain.removeBlocksByNumber(nb); 77  } 78  79  // start mining on top of the new best block 80  minerServer.buildBlockToMine(block, false); 81  82  return true; 83  } 84  85  public boolean revertToSnapshot(int snapshotId) { 86  if (snapshotId <= 0 || snapshotId > this.snapshots.size()) { 87  return false; 88  } 89  90  long newBestBlockNumber = this.snapshots.get(snapshotId - 1); 91  92  this.snapshots = this.snapshots.stream().limit(snapshotId).collect(Collectors.toList()); 93  94  long currentBestBlockNumber = blockchain.getBestBlock().getNumber(); 95  96  if (newBestBlockNumber >= currentBestBlockNumber) { 97  return true; 98  } 99  100  Block block = blockStore.getChainBlockByNumber(newBestBlockNumber); 101  BlockDifficulty difficulty = blockStore.getTotalDifficultyForHash(block.getHash().getBytes()); 102  103  blockchain.setStatus(block, difficulty); 104  105  // To clean pending state, first process the fork 106  transactionPool.processBest(block); 107  // then, clear any reverted transaction 108  transactionPool.removeTransactions(transactionPool.getPendingTransactions()); 109  transactionPool.removeTransactions(transactionPool.getQueuedTransactions()); 110  111  // Remove removed blocks from store 112  for (long nb = blockchain.getBestBlock().getNumber() + 1; nb <= currentBestBlockNumber; nb++) { 113  blockchain.removeBlocksByNumber(nb); 114  } 115  116  // start mining on top of the new best block 117  minerServer.buildBlockToMine(block, false); 118  119  return true; 120  } 121  122  @VisibleForTesting 123  public List<Long> getSnapshots() { 124  return this.snapshots; 125  } 126 }