Coverage Summary for Class: MnrModuleImpl (co.rsk.rpc.modules.mnr)

Class Class, % Method, % Line, %
MnrModuleImpl 0% (0/1) 0% (0/10) 0% (0/48)


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  19 package co.rsk.rpc.modules.mnr; 20  21 import co.rsk.bitcoinj.core.BtcBlock; 22 import co.rsk.bitcoinj.core.BtcTransaction; 23 import co.rsk.bitcoinj.core.Context; 24 import co.rsk.bitcoinj.core.NetworkParameters; 25 import co.rsk.bitcoinj.params.RegTestParams; 26 import co.rsk.config.RskMiningConstants; 27 import co.rsk.mine.MinerServer; 28 import co.rsk.mine.MinerWork; 29 import co.rsk.mine.SubmitBlockResult; 30 import co.rsk.mine.SubmittedBlockInfo; 31 import co.rsk.rpc.exception.JsonRpcSubmitBlockException; 32 import co.rsk.util.ListArrayUtil; 33 import org.bouncycastle.util.encoders.Hex; 34 import org.ethereum.crypto.Keccak256Helper; 35 import org.ethereum.rpc.TypeConverter; 36 import org.slf4j.Logger; 37 import org.slf4j.LoggerFactory; 38  39 import java.util.Arrays; 40 import java.util.Collections; 41 import java.util.List; 42  43 public class MnrModuleImpl implements MnrModule { 44  private static final Logger logger = LoggerFactory.getLogger("web3"); 45  46  private final MinerServer minerServer; 47  48  public MnrModuleImpl(MinerServer minerServer) { 49  this.minerServer = minerServer; 50  } 51  52  @Override 53  public MinerWork getWork() { 54  logger.debug("getWork()"); 55  return minerServer.getWork(); 56  } 57  58  @Override 59  public SubmittedBlockInfo submitBitcoinBlock(String bitcoinBlockHex) { 60  logger.debug("submitBitcoinBlock(): {}", bitcoinBlockHex.length()); 61  62  NetworkParameters params = RegTestParams.get(); 63  new Context(params); 64  65  BtcBlock bitcoinBlock = getBtcBlock(bitcoinBlockHex, params); 66  BtcTransaction coinbase = bitcoinBlock.getTransactions().get(0); 67  68  String blockHashForMergedMining = extractBlockHashForMergedMining(coinbase); 69  70  SubmitBlockResult result = minerServer.submitBitcoinBlock(blockHashForMergedMining, bitcoinBlock); 71  72  return parseResultAndReturn(result); 73  } 74  75  @Override 76  public SubmittedBlockInfo submitBitcoinBlockTransactions(String blockHashHex, String blockHeaderHex, String coinbaseHex, String txnHashesHex) { 77  logger.debug("submitBitcoinBlockTransactions(): {}, {}, {}, {}", blockHashHex, blockHeaderHex, coinbaseHex, txnHashesHex); 78  79  NetworkParameters params = RegTestParams.get(); 80  new Context(params); 81  82  BtcBlock bitcoinBlockWithHeaderOnly = getBtcBlock(blockHeaderHex, params); 83  BtcTransaction coinbase = new BtcTransaction(params, Hex.decode(coinbaseHex)); 84  85  String blockHashForMergedMining = extractBlockHashForMergedMining(coinbase); 86  87  List<String> txnHashes = parseHashes(txnHashesHex); 88  89  SubmitBlockResult result = minerServer.submitBitcoinBlockTransactions(blockHashForMergedMining, bitcoinBlockWithHeaderOnly, coinbase, txnHashes); 90  91  return parseResultAndReturn(result); 92  } 93  94  @Override 95  public SubmittedBlockInfo submitBitcoinBlockPartialMerkle(String blockHashHex, String blockHeaderHex, String coinbaseHex, String merkleHashesHex, String blockTxnCountHex) { 96  logger.debug("submitBitcoinBlockPartialMerkle(): {}, {}, {}, {}, {}", blockHashHex, blockHeaderHex, coinbaseHex, merkleHashesHex, blockTxnCountHex); 97  98  if (merkleHashesHex.isEmpty()) { 99  throw new JsonRpcSubmitBlockException("The list of merkle hashes can't be empty"); 100  } 101  102  NetworkParameters params = RegTestParams.get(); 103  new Context(params); 104  105  BtcBlock bitcoinBlockWithHeaderOnly = getBtcBlock(blockHeaderHex, params); 106  BtcTransaction coinbase = new BtcTransaction(params, Hex.decode(coinbaseHex)); 107  108  String blockHashForMergedMining = extractBlockHashForMergedMining(coinbase); 109  110  List<String> merkleHashes = parseHashes(merkleHashesHex); 111  112  int txnCount = Integer.parseInt(blockTxnCountHex, 16); 113  114  SubmitBlockResult result = minerServer.submitBitcoinBlockPartialMerkle(blockHashForMergedMining, bitcoinBlockWithHeaderOnly, coinbase, merkleHashes, txnCount); 115  116  return parseResultAndReturn(result); 117  } 118  119  private BtcBlock getBtcBlock(String blockHeaderHex, NetworkParameters params) { 120  byte[] bitcoinBlockByteArray = Hex.decode(blockHeaderHex); 121  return params.getDefaultSerializer().makeBlock(bitcoinBlockByteArray); 122  } 123  124  private String extractBlockHashForMergedMining(BtcTransaction coinbase) { 125  byte[] coinbaseAsByteArray = coinbase.bitcoinSerialize(); 126  List<Byte> coinbaseAsByteList = ListArrayUtil.asByteList(coinbaseAsByteArray); 127  128  List<Byte> rskTagAsByteList = ListArrayUtil.asByteList(RskMiningConstants.RSK_TAG); 129  130  int rskTagPosition = Collections.lastIndexOfSubList(coinbaseAsByteList, rskTagAsByteList); 131  byte[] blockHashForMergedMiningArray = new byte[Keccak256Helper.Size.S256.getValue() / 8]; 132  System.arraycopy(coinbaseAsByteArray, rskTagPosition + RskMiningConstants.RSK_TAG.length, blockHashForMergedMiningArray, 0, blockHashForMergedMiningArray.length); 133  return TypeConverter.toJsonHex(blockHashForMergedMiningArray); 134  } 135  136  private List<String> parseHashes(String txnHashesHex) { 137  String[] split = txnHashesHex.split("\\s+"); 138  return Arrays.asList(split); 139  } 140  141  private SubmittedBlockInfo parseResultAndReturn(SubmitBlockResult result) { 142  if ("OK".equals(result.getStatus())) { 143  return result.getBlockInfo(); 144  } else { 145  throw new JsonRpcSubmitBlockException(result.getMessage()); 146  } 147  } 148 }