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 }