Coverage Summary for Class: GenesisMerkleProofBuilder (co.rsk.mine)

Class Class, % Method, % Line, %
GenesisMerkleProofBuilder 0% (0/1) 0% (0/6) 0% (0/25)


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.mine; 19  20 import co.rsk.bitcoinj.core.*; 21 import org.bouncycastle.util.encoders.Hex; 22  23 import java.util.ArrayList; 24 import java.util.List; 25 import java.util.stream.Collectors; 26  27 /** 28  * Builds Merkle proofs with the format used since Genesis until RSKIP 92 activation 29  */ 30 public class GenesisMerkleProofBuilder implements MerkleProofBuilder { 31  32  @Override 33  public byte[] buildFromMerkleHashes( 34  BtcBlock blockWithHeaderOnly, 35  List<String> merkleHashesString, 36  int blockTxnCount) { 37  List<Sha256Hash> merkleHashes = merkleHashesString.stream() 38  .map(mk -> Sha256Hash.wrapReversed(Hex.decode(mk))) 39  .collect(Collectors.toList()); 40  int merkleTreeHeight = (int) Math.ceil(Math.log(blockTxnCount) / Math.log(2)); 41  42  // bitlist will always have ones at the beginning because merkle branch is built for coinbase tx 43  List<Boolean> bitList = new ArrayList<>(); 44  for (int i = 0; i < merkleHashes.size() + merkleTreeHeight; i++) { 45  bitList.add(i < merkleHashes.size()); 46  } 47  48  // bits indicates which nodes are going to be used for building the partial merkle tree 49  // for more information please refer to {@link co.rsk.bitcoinj.core.PartialMerkleTree#buildFromLeaves } method 50  byte[] bits = new byte[(bitList.size() + 7) / 8]; 51  for (int i = 0; i < bitList.size(); i++) { 52  if (bitList.get(i)) { 53  Utils.setBitLE(bits, i); 54  } 55  } 56  57  PartialMerkleTree bitcoinMergedMiningMerkleBranch = new PartialMerkleTree(blockWithHeaderOnly.getParams(), bits, merkleHashes, blockTxnCount); 58  59  return bitcoinMergedMiningMerkleBranch.bitcoinSerialize(); 60  } 61  62  @Override 63  public byte[] buildFromTxHashes( 64  BtcBlock blockWithHeaderOnly, 65  List<String> txHashesString) { 66  List<Sha256Hash> txHashes = txHashesString.stream().map(Sha256Hash::wrap).collect(Collectors.toList()); 67  68  PartialMerkleTree bitcoinMergedMiningMerkleBranch = getBitcoinMergedMerkleBranch(txHashes, blockWithHeaderOnly.getParams()); 69  70  return bitcoinMergedMiningMerkleBranch.bitcoinSerialize(); 71  } 72  73  @Override 74  public byte[] buildFromBlock(BtcBlock bitcoinMergedMiningBlock) { 75  List<Sha256Hash> txHashes = bitcoinMergedMiningBlock.getTransactions().stream() 76  .map(BtcTransaction::getHash) 77  .collect(Collectors.toList()); 78  79  PartialMerkleTree bitcoinMergedMiningMerkleBranch = getBitcoinMergedMerkleBranch(txHashes, bitcoinMergedMiningBlock.getParams()); 80  81  return bitcoinMergedMiningMerkleBranch.bitcoinSerialize(); 82  } 83  84  /** 85  * getBitcoinMergedMerkleBranch returns the Partial Merkle Branch needed to validate that the coinbase tx 86  * is part of the Merkle Tree. 87  * 88  * @param txHashes the bitcoin txs that were included in a block. 89  * @return A Partial Merkle Branch in which you can validate the coinbase tx. 90  */ 91  private static PartialMerkleTree getBitcoinMergedMerkleBranch(List<Sha256Hash> txHashes, NetworkParameters params) { 92  /* 93  We need to convert the txs to a bitvector to choose which ones 94  will be included in the Partial Merkle Tree. 95  96  We need txs.size() / 8 bytes to represent this vector. 97  The coinbase tx is the first one of the txs so we set the first bit to 1. 98  */ 99  byte[] bitvector = new byte[(txHashes.size() + 7) / 8]; 100  Utils.setBitLE(bitvector, 0); 101  return PartialMerkleTree.buildFromLeaves(params, bitvector, txHashes); 102  } 103 }