Coverage Summary for Class: RepositoryLocator (co.rsk.db)
Class |
Method, %
|
Line, %
|
RepositoryLocator |
85.7%
(6/7)
|
90%
(18/20)
|
RepositoryLocator$MockitoMock$584568540 |
RepositoryLocator$MockitoMock$584568540$auxiliary$KiRMJ1KA |
RepositoryLocator$MockitoMock$584568540$auxiliary$VOh8EH4u |
RepositoryLocator$MockitoMock$584568540$auxiliary$WXMh5cW3 |
RepositoryLocator$MockitoMock$584568540$auxiliary$Z01InEHs |
RepositoryLocator$MockitoMock$584568540$auxiliary$zxe20G2q |
Total |
85.7%
(6/7)
|
90%
(18/20)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2019 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.db;
20
21 import co.rsk.crypto.Keccak256;
22 import co.rsk.trie.MutableTrie;
23 import co.rsk.trie.Trie;
24 import co.rsk.trie.TrieStore;
25 import org.ethereum.core.BlockHeader;
26 import org.ethereum.core.Repository;
27 import org.ethereum.crypto.Keccak256Helper;
28 import org.ethereum.db.MutableRepository;
29 import org.ethereum.util.RLP;
30
31 import java.util.Optional;
32
33 import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
34
35 public class RepositoryLocator {
36 // all zeroed, default hash for empty nodes
37 private static final Keccak256 EMPTY_HASH = new Keccak256(Keccak256Helper.keccak256(RLP.encodeElement(EMPTY_BYTE_ARRAY)));
38
39 private final TrieStore trieStore;
40 private final StateRootHandler stateRootHandler;
41
42 public RepositoryLocator(TrieStore store, StateRootHandler stateRootHandler) {
43 this.trieStore = store;
44 this.stateRootHandler = stateRootHandler;
45 }
46
47 /**
48 * Similar to snapshotAt but retrieves an optional instead of throwing an exception
49 * @return an optional {@link RepositorySnapshot}
50 */
51 public Optional<RepositorySnapshot> findSnapshotAt(BlockHeader header) {
52 return mutableTrieSnapshotAt(header).map(MutableRepository::new);
53 }
54
55 /**
56 * Retrieves a snapshot of the state at a particular header
57 * @param header the header to retrieve the state from
58 * @return a read-only {@link RepositorySnapshot}
59 * @throws IllegalArgumentException if the state is not found.
60 */
61 public RepositorySnapshot snapshotAt(BlockHeader header) {
62 return mutableTrieSnapshotAt(header)
63 .map(MutableRepository::new)
64 .orElseThrow(() -> trieNotFoundException(header));
65 }
66
67 /**
68 * Retrieves a repository of the state at a particular header
69 * @param header the header to retrieve the state from
70 * @return a modifiable {@link Repository}
71 * @throws IllegalArgumentException if the state is not found.
72 */
73 public Repository startTrackingAt(BlockHeader header) {
74 return mutableTrieSnapshotAt(header)
75 .map(MutableTrieCache::new)
76 .map(MutableRepository::new)
77 .orElseThrow(() -> trieNotFoundException(header));
78 }
79
80 private IllegalArgumentException trieNotFoundException(BlockHeader header) {
81 return new IllegalArgumentException(String.format(
82 "The trie with root %s is missing in this store", header.getHash()
83 ));
84 }
85
86 private Optional<MutableTrie> mutableTrieSnapshotAt(BlockHeader header) {
87 Keccak256 stateRoot = stateRootHandler.translate(header);
88
89 if (EMPTY_HASH.equals(stateRoot)) {
90 return Optional.of(new MutableTrieImpl(trieStore, new Trie(trieStore)));
91 }
92
93 Optional<Trie> trie = trieStore.retrieve(stateRoot.getBytes());
94
95 return trie.map(t -> new MutableTrieImpl(trieStore, t));
96 }
97 }