Coverage Summary for Class: Rskip92MerkleProofValidator (co.rsk.validators)
Class |
Class, %
|
Method, %
|
Line, %
|
Rskip92MerkleProofValidator |
0%
(0/1)
|
0%
(0/4)
|
0%
(0/18)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2018 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 package co.rsk.validators;
19
20 import co.rsk.bitcoinj.core.Sha256Hash;
21 import co.rsk.peg.utils.MerkleTreeUtils;
22 import org.ethereum.config.Constants;
23
24 import java.util.Arrays;
25 import java.util.stream.IntStream;
26 import java.util.stream.Stream;
27
28 /**
29 * Validates RSKIP 92 Merkle proofs
30 */
31 public class Rskip92MerkleProofValidator implements MerkleProofValidator {
32
33 private final byte[] pmtSerialized;
34
35 public Rskip92MerkleProofValidator(byte[] pmtSerialized, boolean isRskip180Enabled) {
36 if (isRskip180Enabled) {
37 if (pmtSerialized == null) {
38 throw new IllegalArgumentException("Partial merkle tree is <null>");
39 }
40
41 int maxMerkleProofLength = Constants.getMaxBitcoinMergedMiningMerkleProofLength();
42 if (pmtSerialized.length > maxMerkleProofLength) {
43 throw new IllegalArgumentException("Partial merkle tree's size is greater than " + maxMerkleProofLength);
44 }
45 }
46
47 if ((pmtSerialized.length % Sha256Hash.LENGTH) != 0) {
48 throw new IllegalArgumentException("Partial merkle tree does not have the expected format");
49 }
50
51 this.pmtSerialized = pmtSerialized;
52 }
53
54 @Override
55 public boolean isValid(Sha256Hash expectedRoot, Sha256Hash coinbaseHash) {
56 Sha256Hash root = streamHashes().reduce(coinbaseHash, MerkleTreeUtils::combineLeftRight);
57 return root.equals(expectedRoot);
58 }
59
60 private Stream<Sha256Hash> streamHashes() {
61 return IntStream.range(0, pmtSerialized.length / Sha256Hash.LENGTH)
62 .mapToObj(this::getHash);
63 }
64
65 private Sha256Hash getHash(int index) {
66 int start = index * Sha256Hash.LENGTH;
67 int end = (index + 1) * Sha256Hash.LENGTH;
68 byte[] hash = Arrays.copyOfRange(pmtSerialized, start, end);
69 return Sha256Hash.wrap(hash);
70 }
71 }