Search in sources :

Example 31 with BtcBlock

use of co.rsk.bitcoinj.core.BtcBlock in project rskj by rsksmart.

the class BridgeSupport method validationsForRegisterBtcTransaction.

@VisibleForTesting
protected boolean validationsForRegisterBtcTransaction(Sha256Hash btcTxHash, int height, byte[] pmtSerialized, byte[] btcTxSerialized) throws BlockStoreException, VerificationException.EmptyInputsOrOutputs, BridgeIllegalArgumentException {
    // Validates height and confirmations for tx
    try {
        int acceptableConfirmationsAmount = bridgeConstants.getBtc2RskMinimumAcceptableConfirmations();
        if (!BridgeUtils.validateHeightAndConfirmations(height, getBtcBlockchainBestChainHeight(), acceptableConfirmationsAmount, btcTxHash)) {
            return false;
        }
    } catch (Exception e) {
        String panicMessage = String.format("Btc Tx %s Supplied Height is %d but should be greater than 0", btcTxHash, height);
        logger.warn(panicMessage);
        panicProcessor.panic("btclock", panicMessage);
        return false;
    }
    // Validates pmt size
    if (!PartialMerkleTreeFormatUtils.hasExpectedSize(pmtSerialized)) {
        throw new BridgeIllegalArgumentException("PartialMerkleTree doesn't have expected size");
    }
    // Calculates merkleRoot
    Sha256Hash merkleRoot;
    try {
        NetworkParameters networkParameters = bridgeConstants.getBtcParams();
        merkleRoot = BridgeUtils.calculateMerkleRoot(networkParameters, pmtSerialized, btcTxHash);
        if (merkleRoot == null) {
            return false;
        }
    } catch (VerificationException e) {
        throw new BridgeIllegalArgumentException(e.getMessage(), e);
    }
    // Validates inputs count
    logger.info("Going to validate inputs for btc tx {}", btcTxHash);
    BridgeUtils.validateInputsCount(btcTxSerialized, activations.isActive(ConsensusRule.RSKIP143));
    // Check the the merkle root equals merkle root of btc block at specified height in the btc best chain
    // BTC blockstore is available since we've already queried the best chain height
    logger.trace("Getting btc block at height: {}", height);
    BtcBlock blockHeader = btcBlockStore.getStoredBlockAtMainChainHeight(height).getHeader();
    logger.trace("Validating block merkle root at height: {}", height);
    if (!isBlockMerkleRootValid(merkleRoot, blockHeader)) {
        String panicMessage = String.format("Btc Tx %s Supplied merkle root %s does not match block's merkle root %s", btcTxHash.toString(), merkleRoot, blockHeader.getMerkleRoot());
        logger.warn(panicMessage);
        panicProcessor.panic("btclock", panicMessage);
        return false;
    }
    return true;
}
Also used : NetworkParameters(co.rsk.bitcoinj.core.NetworkParameters) Sha256Hash(co.rsk.bitcoinj.core.Sha256Hash) VerificationException(co.rsk.bitcoinj.core.VerificationException) BtcBlock(co.rsk.bitcoinj.core.BtcBlock) VMException(org.ethereum.vm.exception.VMException) UTXOProviderException(co.rsk.bitcoinj.core.UTXOProviderException) VerificationException(co.rsk.bitcoinj.core.VerificationException) InsufficientMoneyException(co.rsk.bitcoinj.core.InsufficientMoneyException) AddressFormatException(co.rsk.bitcoinj.core.AddressFormatException) IOException(java.io.IOException) BlockStoreException(co.rsk.bitcoinj.store.BlockStoreException) PeginInstructionsException(co.rsk.peg.pegininstructions.PeginInstructionsException) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 32 with BtcBlock

use of co.rsk.bitcoinj.core.BtcBlock in project rskj by rsksmart.

the class BridgeSupport method registerBtcCoinbaseTransaction.

public void registerBtcCoinbaseTransaction(byte[] btcTxSerialized, Sha256Hash blockHash, byte[] pmtSerialized, Sha256Hash witnessMerkleRoot, byte[] witnessReservedValue) throws VMException {
    Context.propagate(btcContext);
    try {
        this.ensureBtcBlockStore();
    } catch (BlockStoreException | IOException e) {
        logger.warn("Exception in registerBtcCoinbaseTransaction", e);
        throw new VMException("Exception in registerBtcCoinbaseTransaction", e);
    }
    Sha256Hash btcTxHash = BtcTransactionFormatUtils.calculateBtcTxHash(btcTxSerialized);
    if (witnessReservedValue.length != 32) {
        logger.warn("[btcTx:{}] WitnessResevedValue length can't be different than 32 bytes", btcTxHash);
        throw new BridgeIllegalArgumentException("WitnessResevedValue length can't be different than 32 bytes");
    }
    if (!PartialMerkleTreeFormatUtils.hasExpectedSize(pmtSerialized)) {
        logger.warn("[btcTx:{}] PartialMerkleTree doesn't have expected size", btcTxHash);
        throw new BridgeIllegalArgumentException("PartialMerkleTree doesn't have expected size");
    }
    Sha256Hash merkleRoot;
    try {
        PartialMerkleTree pmt = new PartialMerkleTree(bridgeConstants.getBtcParams(), pmtSerialized, 0);
        List<Sha256Hash> hashesInPmt = new ArrayList<>();
        merkleRoot = pmt.getTxnHashAndMerkleRoot(hashesInPmt);
        if (!hashesInPmt.contains(btcTxHash)) {
            logger.warn("Supplied Btc Tx {} is not in the supplied partial merkle tree", btcTxHash);
            return;
        }
    } catch (VerificationException e) {
        logger.warn("[btcTx:{}] PartialMerkleTree could not be parsed", btcTxHash);
        throw new BridgeIllegalArgumentException(String.format("PartialMerkleTree could not be parsed %s", ByteUtil.toHexString(pmtSerialized)), e);
    }
    // Check merkle root equals btc block merkle root at the specified height in the btc best chain
    // Btc blockstore is available since we've already queried the best chain height
    StoredBlock storedBlock = btcBlockStore.getFromCache(blockHash);
    if (storedBlock == null) {
        logger.warn("[btcTx:{}] Block not registered", btcTxHash);
        throw new BridgeIllegalArgumentException(String.format("Block not registered %s", blockHash.toString()));
    }
    BtcBlock blockHeader = storedBlock.getHeader();
    if (!blockHeader.getMerkleRoot().equals(merkleRoot)) {
        String panicMessage = String.format("Btc Tx %s Supplied merkle root %s does not match block's merkle root %s", btcTxHash.toString(), merkleRoot, blockHeader.getMerkleRoot());
        logger.warn(panicMessage);
        panicProcessor.panic("btclock", panicMessage);
        return;
    }
    BtcTransaction btcTx = new BtcTransaction(bridgeConstants.getBtcParams(), btcTxSerialized);
    btcTx.verify();
    Sha256Hash witnessCommitment = Sha256Hash.twiceOf(witnessMerkleRoot.getReversedBytes(), witnessReservedValue);
    if (!witnessCommitment.equals(btcTx.findWitnessCommitment())) {
        logger.warn("[btcTx:{}] WitnessCommitment does not match", btcTxHash);
        throw new BridgeIllegalArgumentException("WitnessCommitment does not match");
    }
    CoinbaseInformation coinbaseInformation = new CoinbaseInformation(witnessMerkleRoot);
    provider.setCoinbaseInformation(blockHeader.getHash(), coinbaseInformation);
    logger.warn("[btcTx:{}] Registered coinbase information", btcTxHash);
}
Also used : BlockStoreException(co.rsk.bitcoinj.store.BlockStoreException) StoredBlock(co.rsk.bitcoinj.core.StoredBlock) CoinbaseInformation(co.rsk.peg.bitcoin.CoinbaseInformation) Sha256Hash(co.rsk.bitcoinj.core.Sha256Hash) BtcTransaction(co.rsk.bitcoinj.core.BtcTransaction) ArrayList(java.util.ArrayList) IOException(java.io.IOException) VMException(org.ethereum.vm.exception.VMException) PartialMerkleTree(co.rsk.bitcoinj.core.PartialMerkleTree) VerificationException(co.rsk.bitcoinj.core.VerificationException) BtcBlock(co.rsk.bitcoinj.core.BtcBlock)

Example 33 with BtcBlock

use of co.rsk.bitcoinj.core.BtcBlock in project rskj by rsksmart.

the class BlockHeaderContractTest method mineBlock.

private Block mineBlock(Block parent, RskAddress coinbase) {
    NetworkParameters networkParameters = RegTestParams.get();
    BlockGenerator blockGenerator = new BlockGenerator(config.getNetworkConstants(), config.getActivationConfig());
    Block childBlock = blockGenerator.createChildBlock(parent, new ArrayList<>(), new ArrayList<>(), parent.getDifficulty().asBigInteger().longValue(), MIN_GAS_PRICE, parent.getGasLimit(), coinbase);
    Block newBlock = blockFactory.cloneBlockForModification(childBlock);
    byte[] prefix = new byte[1000];
    byte[] compressedTag = Arrays.concatenate(prefix, RskMiningConstants.RSK_TAG);
    byte[] mergedMiningHash = childBlock.getHashForMergedMining();
    BtcTransaction mergedMiningCoinbaseTransaction = MinerUtils.getBitcoinMergedMiningCoinbaseTransaction(networkParameters, mergedMiningHash);
    BtcBlock mergedMiningBlock = MinerUtils.getBitcoinMergedMiningBlock(networkParameters, mergedMiningCoinbaseTransaction);
    BigInteger targetDifficulty = DifficultyUtils.difficultyToTarget(parent.getDifficulty());
    new BlockMiner(config.getActivationConfig()).findNonce(mergedMiningBlock, targetDifficulty);
    newBlock.setBitcoinMergedMiningHeader(mergedMiningBlock.cloneAsHeader().bitcoinSerialize());
    byte[] merkleProof = MinerUtils.buildMerkleProof(config.getActivationConfig(), pb -> pb.buildFromBlock(mergedMiningBlock), newBlock.getNumber());
    newBlock.setBitcoinMergedMiningMerkleProof(merkleProof);
    byte[] additionalTag = Arrays.concatenate(ADDITIONAL_TAG, mergedMiningHash);
    byte[] mergedMiningTx = org.bouncycastle.util.Arrays.concatenate(compressedTag, mergedMiningHash, additionalTag);
    newBlock.setBitcoinMergedMiningCoinbaseTransaction(mergedMiningTx);
    return newBlock;
}
Also used : NetworkParameters(co.rsk.bitcoinj.core.NetworkParameters) BtcTransaction(co.rsk.bitcoinj.core.BtcTransaction) BtcBlock(co.rsk.bitcoinj.core.BtcBlock) BtcBlock(co.rsk.bitcoinj.core.BtcBlock) BigInteger(java.math.BigInteger) BlockMiner(co.rsk.blockchain.utils.BlockMiner) BlockGenerator(co.rsk.blockchain.utils.BlockGenerator)

Example 34 with BtcBlock

use of co.rsk.bitcoinj.core.BtcBlock in project rskj by rsksmart.

the class MinerServerImpl method processSolution.

private SubmitBlockResult processSolution(String blockHashForMergedMining, BtcBlock blockWithHeaderOnly, BtcTransaction coinbase, Function<MerkleProofBuilder, byte[]> proofBuilderFunction, boolean lastTag) {
    Block newBlock;
    Keccak256 key = new Keccak256(TypeConverter.removeZeroX(blockHashForMergedMining));
    synchronized (lock) {
        if (!submissionRateLimitHandler.isSubmissionAllowed()) {
            String message = "Cannot publish block, block submission rate limit exceeded";
            logger.warn(message);
            return new SubmitBlockResult("ERROR", message);
        }
        submissionRateLimitHandler.onSubmit();
        Block workingBlock = blocksWaitingForPoW.get(key);
        if (workingBlock == null) {
            String message = "Cannot publish block, could not find hash " + blockHashForMergedMining + " in the cache";
            logger.warn(message);
            return new SubmitBlockResult("ERROR", message);
        }
        newBlock = blockFactory.cloneBlockForModification(workingBlock);
        logger.debug("blocksWaitingForPoW size {}", blocksWaitingForPoW.size());
    }
    logger.info("Received block {} {}", newBlock.getNumber(), newBlock.getHash());
    newBlock.setBitcoinMergedMiningHeader(blockWithHeaderOnly.cloneAsHeader().bitcoinSerialize());
    newBlock.setBitcoinMergedMiningCoinbaseTransaction(compressCoinbase(coinbase.bitcoinSerialize(), lastTag));
    newBlock.setBitcoinMergedMiningMerkleProof(MinerUtils.buildMerkleProof(activationConfig, proofBuilderFunction, newBlock.getNumber()));
    newBlock.seal();
    if (!isValid(newBlock)) {
        String message = "Invalid block supplied by miner: " + newBlock.getPrintableHash() + " " + newBlock.getPrintableHashForMergedMining() + " at height " + newBlock.getNumber();
        logger.error(message);
        return new SubmitBlockResult("ERROR", message);
    } else {
        ImportResult importResult = ethereum.addNewMinedBlock(newBlock);
        logger.info("Mined block import result is {}: {} {} at height {}", importResult, newBlock.getPrintableHash(), newBlock.getPrintableHashForMergedMining(), newBlock.getNumber());
        SubmittedBlockInfo blockInfo = new SubmittedBlockInfo(importResult, newBlock.getHash().getBytes(), newBlock.getNumber());
        return new SubmitBlockResult("OK", "OK", blockInfo);
    }
}
Also used : BtcBlock(co.rsk.bitcoinj.core.BtcBlock) Keccak256(co.rsk.crypto.Keccak256)

Example 35 with BtcBlock

use of co.rsk.bitcoinj.core.BtcBlock in project rskj by rsksmart.

the class Web3RskImpl method mnr_submitBitcoinBlock.

public SubmittedBlockInfo mnr_submitBitcoinBlock(String bitcoinBlockHex) {
    logger.debug("mnr_submitBitcoinBlock(): {}", bitcoinBlockHex.length());
    NetworkParameters params = RegTestParams.get();
    new Context(params);
    BtcBlock bitcoinBlock = getBtcBlock(bitcoinBlockHex, params);
    BtcTransaction coinbase = bitcoinBlock.getTransactions().get(0);
    String blockHashForMergedMining = extractBlockHashForMergedMining(coinbase);
    SubmitBlockResult result = minerServer.submitBitcoinBlock(blockHashForMergedMining, bitcoinBlock);
    return parseResultAndReturn(result);
}
Also used : Context(co.rsk.bitcoinj.core.Context) NetworkParameters(co.rsk.bitcoinj.core.NetworkParameters) BtcTransaction(co.rsk.bitcoinj.core.BtcTransaction) BtcBlock(co.rsk.bitcoinj.core.BtcBlock)

Aggregations

BtcBlock (co.rsk.bitcoinj.core.BtcBlock)37 Test (org.junit.Test)17 StoredBlock (co.rsk.bitcoinj.core.StoredBlock)16 NetworkParameters (co.rsk.bitcoinj.core.NetworkParameters)11 BtcTransaction (co.rsk.bitcoinj.core.BtcTransaction)10 Sha256Hash (co.rsk.bitcoinj.core.Sha256Hash)9 Repository (org.ethereum.core.Repository)8 Context (co.rsk.bitcoinj.core.Context)7 BigInteger (java.math.BigInteger)7 MutableRepository (org.ethereum.db.MutableRepository)6 BlockStoreException (co.rsk.bitcoinj.store.BlockStoreException)4 BlockGenerator (co.rsk.blockchain.utils.BlockGenerator)3 SubmitBlockResult (co.rsk.mine.SubmitBlockResult)3 InputStream (java.io.InputStream)3 ActivationConfig (org.ethereum.config.blockchain.upgrades.ActivationConfig)3 MessageSerializer (co.rsk.bitcoinj.core.MessageSerializer)2 VerificationException (co.rsk.bitcoinj.core.VerificationException)2 BlockMiner (co.rsk.blockchain.utils.BlockMiner)2 RskSystemProperties (co.rsk.config.RskSystemProperties)2 Keccak256 (co.rsk.crypto.Keccak256)2